I am wondering what are the guarantees that compilers make to ensure that streaming writes to memory have visible effects in other threads.
I know countless cases where this is problematic, and I'm sure that if you are interested in an answer, you know that too, but please focus on the cases that I will present.
More precisely, I am concerned about circumstances that could lead to threads losing memory updates made by other threads. I don’t care (at the moment) if the updates are non-atomic or highly synchronized: as long as the corresponding threads notice the changes, I will be happy.
I hope compilers make a distinction between two types of access variables:
- Access to variables that must have an address;
- Access to variables that do not necessarily have an address.
For example, if you take this snippet:
void sleepingbeauty() { int i = 1; while (i) sleep(1); }
Since i is local, I assume that my compiler can optimize it and just let the sleeping beauty fall to eternal sleep.
void onedaymyprincewillcome(int* i); void sleepingbeauty() { int i = 1; onedaymyprincewillcome(&i); while (i) sleep(1); }
Since i is local, but its address is taken and passed to another function, I assume that my compiler now finds out that it is an “addressable” variable and generates read memory to ensure that perhaps someday the prince will come.
int i = 1; void sleepingbeauty() { while (i) sleep(1); }
Since i is global, I assume that my compiler knows that the variable has an address and will generate a read for it, not a value caching.
void sleepingbeauty(int* ptr) { *ptr = 1; while (*ptr) sleep(1); }
I hope the dereference operator is clear enough so that my compiler generates memory readable at each iteration of the loop.
I am sure that this is the memory access model used by each C and C ++ compiler, but I do not think there are any guarantees. In fact, C ++ 03 is even blind to the existence of threads, so this question doesn’t even make sense given the standard. I'm not sure about C, though.
Is there some kind of documentation out there that indicates whether I am right or wrong? I know that these are dirty waters, since they may not meet the standards, it seems to me an important issue.
Besides the compiler that generates the read, I also fear that the CPU cache may technically preserve the obsolete value, and that although my compiler has done everything possible to fetch the read and write, the values ​​are never synchronized between threads. Could this happen?