0

Am I the only who thinks so? [Real question in a second.]

Besides the great confusion about it, and its mixing with mutexes or other locking mechanisms, when I am dealing with thread safety situation, I always have to discard any use of volatile, because it simply does not do anything useful.

volatile "forbids any reordering or caching of read/writes", but this is not of much use as long as volatile just tags a single object (and taints it, as it won't be any longer a "normal" object).

Consider this:

Thread A            Thread B
reads vars
                    locks mutex (gets access)
locks mutex (waits)
                    writes some vars
                    releases mutex
reads vars again
releases mutex

Now, the compiler might want to optimize the two thread A's reads saving some of the results in registers. You say I should declare those vars as volatile. I say that I don't want to flag everything as volatile, because volatile is transparent as a stone and I have to duplicate 50% of my code to support volatile types. You (he) say that locking a mutex (at least a POSIX mutex) is either something that a compiler recognizes, and manages correctly, either it's a call to a library (inaccessible to the compiler) that can change the world, so the compiler will not assume anything after such call. I say that this is too implementation dependent, very low level stuff (and I don't want to browse dev docs for day to day programming). And worse, it can suddenly change if for some reason the "external library", for any legit reason, becomes accessible to the compiler (maybe the author transforms the function in a template that has to be included in a header... whatever).

So, in my opinion, volatile is totally useless (and misleading), unless for some very low level stuff (device read maybe, but I'm not competent in such field).

Much better would be some other way to tell explicitly to the compiler that it has to discard any assumption about any variable, and every subsequent read must be a true read from memory. But I cannot imagine anything better than calling a dummy external function, and that would have the same issues that I have outlined before. Is there an elegant way to do so?

Community
  • 1
  • 1
Lorenzo Pistone
  • 5,028
  • 3
  • 34
  • 65
  • Your opinion is incorrect. Sorry. – Jonathan Grynspan Jun 05 '12 at 22:16
  • 3
    It is my understanding that `volatile` was intended for accessing IO ports and similar types of magic memory locations on machines. – sarnold Jun 05 '12 at 22:17
  • 1
    Your opinion is an opinion. This site is about facts. Sorry. – Don Roby Jun 05 '12 at 22:17
  • Why wheren't you able to just ask your question, without all that fuzz? `volatile` is not useless, maybe you didn't understand it completely, but your question is a valid one, what a pity. – Jens Gustedt Jun 05 '12 at 22:24
  • I don't think this should be closed, it's a valid, in-depth question, and I liked the answer. – lucas clemente Jun 05 '12 at 22:24
  • To those who locked the question. I might have been too wordy before getting to the actual question, but there is one question. And it has even been address (correctly I guess) by Jens – Lorenzo Pistone Jun 05 '12 at 22:24
  • @JensGustedt the buzz is there because sometimes I get precooked answers on SO (and on a tricky topic like this, maybe even wrong ones). This was to explain thoroughly my thoughts. – Lorenzo Pistone Jun 05 '12 at 22:27
  • 1
    @LorenzoPistone, I completely understand why they closed it, such rants don't have their place here. You could try to edit your post to give it a more agreeable tone. – Jens Gustedt Jun 05 '12 at 22:36
  • 1
    If you edit the question removing the rant, I'll vote to reopen. – Don Roby Jun 05 '12 at 23:02
  • "You say I should declare those vars as `volatile`" Who says that? At least in C++11 what you're looking for are the specifications on what synchronizes with what. If the memory ordering used with that mutex is such that the release synchronizes with the other thread acquiring the mutex, then the thread will see the modifications made by the other thread, no `volatile` necessary. – bames53 Jun 06 '12 at 00:04

3 Answers3

8

I work with low level stuff, here's an example of where it's useful.

volatile uint32_t *foo = <<<a register on a pci device>>> 

It is possible that when reading foo multiple times, I'll get a different result. This is because an external source (the pci device) is modifying it. For example, foo could mean the current time.

It is also possible that when I write to foo, that it has very little to do with what might come out. For example, I might have a register that stores some alert bits. I'll write to those bits to clear them. So if a register foo has value 0x72, I might write 0x2 to the register, which could cause the resultant value in that register to be 0x70.

volatile allows me to use these semantics.

Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
2

Volatile isn't meant as a way of magic-ing away issues of multi-threaded code. It's used when the value of a variable or a memory location can change without the compiler (or even the CPU) having any way of knowing

See Volatile classes in C++ for a fuller explanantion

Community
  • 1
  • 1
Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
2

The new C standard, C11, has what you are calling for. First of all, it has a thread model and a detailed "happened before" relation that extends to threads. And it has a atomic_thread_fence operation that does what you are searching for.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • So basically, I have to pray God that my code works before switching to C++11 (which I've experimented with ,but still has no 100% perfect support from g++)? – Lorenzo Pistone Jun 05 '12 at 22:22
  • I was talking about C11, not C++11, but as far as I remember they agree on this point. gcc (and thus g++) already has these features, only with a slightly different syntax, so by defining simple macros that emulate the standard functions. In any case, the C11 model for "sequenced before" and "happen before" is a good (but difficult) read. Maybe even it could convince you that `volatile` can be useful at times :) – Jens Gustedt Jun 05 '12 at 22:30