Hi, I am working on a project with boost::threads, and I need to be absolutely sure that the method calls between mutex::lock() and mutex::unlock() are not reordered when compiled with different optimizations and compilers. I believe the volatile keyword may be of some use, but honestly, I am unsure whether or not I am using it correctly. Here is some example code:
class obj : boost::mutex {
std::vector<int> data;
void foo(int x) {
lock();
data.push_back(x);
unlock();
x = x*x;
lock();
data.push_back(x);
unlock();
}
void bar(int x) volatile {
lock();
data.push_back(x);
unlock();
x = x*x;
lock();
data.push_back(x);
unlock();
}
};
int main() {
obj o;
o.foo(2); // not volatile
o.bar(2); // is volatile
}
So, my question is: how can I be sure the lock and unlock functions are not reordered? Since there are no data dependencies between the mutex lock and the data, the compiler may see two function calls on a related object followed by two functions calls on another related object. Then it may decide to reorder the function calls to put lock() unlock() together followed by data.push_back(x), data.push_back(x).
I have a feeling the volatile function bar may maintain the order, but I am also not sure what other undesirable side effects the volatile keyword may have.
I don't think optimizations arbitrarily reorder your code...that would cause a lot of problems. Other than that, this locking isn't exception safe either.