tc::change

Hello,

welcome to this blog of our development work at think-cell. It will be mainly about programming in general and more specifically about C++. Our platforms are mainly Windows and macOS, with a bit of web development sprinkled in. We will write about anything that comes to our mind, architectural decisions, little nuggets of wisdom we found or rants about bugs in 3rd party software that leave us frustrated.

At think-cell, we are writing mainly in C++, with some in-house Python scripts mixed in. We built our own in-house library which builds on top of Boost and the C++ Standard Library, and strives to follow the C++ Standard Library in conventions such as names, so that new users find it easy to get started. It is on GitHub and free to use under the Boost license.

I want to get started with a little utility that proved surprisingly useful for us and that has a bit more thinking behind it than is apparent at first sight.

We all know the concept of a dirty flag, which is set somewhere indicating some work to be done, and then queried and reset elsewhere where the work actually happens:

…
dirty=true;
…
if(dirty) {
    dirty=false;
    … do work …
}

Easy enough. There is a degree of freedom here though: do you reset the flag before or after the work is done? You may favor resetting it afterwards:

…
dirty=true;
…
if(dirty) {
    … do work …
    dirty=false;
}

This seems more expressive: you only say you are done with the work when you actually are. But is it practical? Clearly, if busy is not checked while doing work, it does not matter. What if it is checked? In particular, it could be that during the work, the part of the code doing work is being reentered. If you reset dirty early, the work will be skipped. If you reset it late, it won’t. What’s better?

…
dirty=true;
…
if(dirty) {
    … work part 1 …
    reenter_myself();
    … work part 2 …
    dirty=false;
}

At the time of reentrance, only part 1 of the work will be done, no matter how often you reenter the code doing work. Repeating part 1 on reentrance is likely at best not going to help, and at worst leads to an infinite recursion. To be correct, in any case, you must structure the work such that part 1 is sufficient for the code running inside the reentering code path.

If we accept that reasoning, resetting dirty early is always better. If part 1 is not sufficient, the code is incorrect anyway. If it is, we avoid redundant work and possibly an infinite recursion.

In our library available at GitHub, we packaged this insight into a little utility, tc::change, that is an assignment with the additional feature to return if something has changed:

…
dirty=true;
…
if(tc::change(dirty, false)) {
    … do work …
}

Besides for boolean flags, it also useful for other values where changing them entails some dependent work:

if(tc::change(size, screen_size())) {
    … consequences of screen size change …
}

We use tc::change sooo much. Try it!

— by Arno Schödl

Do you have feedback? Send us a message at devblog@think-cell.com !

Sign up for blog updates

Don't miss out on new posts! Sign up to receive a notification whenever we publish a new article.

Just submit your email address below. Be assured that we will not forward your email address to any third party.

Please refer to our privacy policy on how we protect your personal data.

Share