I have following code:
bool sync=false;
int* ptr=NULL;
std::thread t([&](){
do_a(); // long-time operation
while(!sync){
std::atomic_thread_fence(std::memory_order_acquire);
}
do_b(ptr);
});
int val=do_c(); //long-time operation
ptr=&val;
sync=true;
std::atomic_thread_fence(std::memory_order_release);
....
But whet I start this on multiprocessor computer, it sometimes happen, that do_b() is started with null pointer. Indon't uneerstand well this behaviour. Does compiler do some optimalizations? Or do I use fences wrong? Does these fences ensure synchronization of data between threads?
Thank you for your tihe and help.
Your program tries to write the two memory locations (ptr, sync) in that order; but you haven’t told your compiler and or cpu that this is necessary. Your compiler is free to re-arrange the order of memory writes to suit its goals (winning meaningless benchmarks). Your cpu is free to re-arrange memory writes to suit its goals (reduced bus contention, meaningless benchmarks).
So, first you should tell your compiler that it is important that it implement the order you desire. You can accomplish this with the std::atomic, or possibly volatile directives(*).
Secondly, you need to tell your cpu that you are depending upon the visible ordering of these stores. In a single cpu, the program order (above) and visible order are the same. In multiple cpus, they not only aren’t necessarily the same, but can vary with current and past system activity. Thus @DanielLangr’s comment about the fence location. The fence informs the cpu that all stores preceding the fence must be visible before any stores following the fence.
(*) Benchmark-focussed compiler writers have managed to reduce volatile to near meaninglessness, demonstrating the contempt compiler writers hold for their actual customers. Oddly, the ‘write those bits in machine language’ has proved to be more maintainable than relying on the artifacts of ‘de jour’ standards writers. The advent of ‘smart linkers’ may finally neuter systems programming languages in a way that 30 years of standards committees failed to.