Suppose I have the following code:
struct Obj {
mutable bool valueIsCached_;
mutable int value_;
const int parameter_;
Obj (int parameter) : valueIsCached_ (false), parameter_ (parameter) {
}
int getValue () const {
if (!valueIsCached) {
value_ = calculateValue (); // #1
valueIsCached_ = true; // #2
}
return value_;
}
private:
int calculateValue () {
/* calculate value based on parameter and return it;
return value only depends on value of parameter_
(no side effects; no dependence on global state)
*/
}
};
This code is, obviously, thread-safe if the compiler does not reorder the lines marked #1 and #2. The worst thing which can happen is multiple calculation of value_. The code, however, gets thread-unsafe as soon as we cannot guarantee that #2 happens after #1.
- How can we avoid this?
- Do things get worse if the type of
value_is, e.g., astruct?
You need to insert a barrier. Here’s code for VC++:
Note that this is assuming
calculateValueis thread-safe, because it can be called by multiple threads, and that writing tovalue_andvalueIsCached_more than once is safe.