volatile is ignored by my compiler?

  • Permalink
  • submit to reddit
  • Email
  • Follow


Hi,

I am using g++ to compile my C++ code.

Here is the simplified code:

class A {
     public:
         void change();
         void doSomething();
     private:
         volatile bool ready;
}

A::A() : ready(false) {}

A::change() {
     printf("changed!\n");
     ready=true;
}

A::doSomething() {
     // the actual code is not an infinite loop but very close --
doSomething is being called at very high frequency without a while
loop.
     while(true) {
         if (ready) printf("it is ready\n");
         else printf("it is not ready\n");
     }
}

One of the threads will call A.change(), and another thread will call
A.doSomething().
Sometimes, I have the following output:
it is not ready
it is not ready
it is not ready
changed!
it is not ready
it is not ready
it is not ready
it is not ready

And I let the program continue for few minutes.  It still prints "it
is not ready".

Any idea?

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Hei 11/10/2009 2:28:56 AM

See related articles to this posting

On 10 Nov., 09:28, Hei <hchan1...@gmail.com> wrote:
> Hi,
>
> I am using g++ to compile my C++ code.
>
> Here is the simplified code:
>
> class A {
>      public:
>          void change();
>          void doSomething();
>      private:
>          volatile bool ready;
>
> }
>
> A::A() : ready(false) {}
>
> A::change() {
>      printf("changed!\n");
>      ready=true;
>
> }
>
> A::doSomething() {
>      // the actual code is not an infinite loop but very close --
> doSomething is being called at very high frequency without a while
> loop.
>      while(true) {
>          if (ready) printf("it is ready\n");
>          else printf("it is not ready\n");
>      }
>
> }
>
> One of the threads will call A.change(), and another thread will call
> A.doSomething().
> Sometimes, I have the following output:
> it is not ready
> it is not ready
> it is not ready
> changed!
> it is not ready
> it is not ready
> it is not ready
> it is not ready
>
> And I let the program continue for few minutes.  It still prints "it
> is not ready".
>
> Any idea?

{ edits: quoted banner removed. please don't quote the banner. -mod }

Are you sure that you use the same instance of A when calling
doSomething?

Peer


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Peer 11/10/2009 7:02:37 AM

> And I let the program continue for few minutes.  It still prints "it
> is not ready".
>
> Any idea?

Are you sure your threads are accessing the _same_ instance of class A you
are using and not that each thread is accessing it's own thread local copy?

You could test this easily by adding printfs to display "this" pointer & see
if they match!

void A::change() {
     printf("change this=%p\n", this);
      printf("changed!\n");
      ready=true;
}

void A::doSomething() {
     printf("doSomething this=%p\n", this);
      while(true) {
                 if (ready) printf("it is ready\n");
          else printf("it is not ready\n");
      }
}

If they don't print equal then you are definately using different instances.
If they do print equal I'd need more code to see what the problem is.

Hope this helps.

Chris



-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Chris 11/10/2009 7:03:06 AM

Hei wrote:
> 
> And I let the program continue for few minutes.  It still prints "it
> is not ready".
> 
> Any idea?
> 

Does the compiler's documentation tell you that this will work? The 
language definition does not require volatile to impose synchronization 
on a variable that's accessed from multiple threads. If one thread is 
running on one CPU and the other thread on another CPU, writing from one 
thread writes to that CPU's cache; the other CPU has its own cache, and 
won't see that change until the write is flushed to main memory and the 
previously read value is replaced from main memory. To make that happen, 
you need synchronization; typically through a mutex or a condition variable.

-- 
   Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Pete 11/10/2009 3:30:50 PM

On Nov 10, 9:28 am, Hei <hchan1...@gmail.com> wrote:
> Hi,
>          volatile bool ready;
>
> A::A() : ready(false) {}
>
> A::change() {
>      printf("changed!\n");
>      ready=true;
>
> }
>
> A::doSomething() {
>      // the actual code is not an infinite loop but very close --
> doSomething is being called at very high frequency without a while
> loop.
>      while(true) {
>          if (ready) printf("it is ready\n");
>          else printf("it is not ready\n");
>      }
>
> }
>
> One of the threads will call A.change(), and another thread will call
> A.doSomething().

The semantics of volatile are very specific, and they are intended to
read and write special memory locations (e.g. memory-mapped I/O
registers of periphery), not for thread communication. Volatile forces
the compiler to assume that the variable can change unexpectedly, that
simply writing or even reading it can have side effects, and thus to
never lift it to a register or reorder/omit accesses.
Volatile does not force the CPU(s) to do anything, though. You're
accessing a simple variable, an ordinary memory location. The CPU,
unlike the compiler, isn't fooled by you - it knows that no periphery
is going to change this location. Any core therefore can, depending on
the architecture's cache consistency model, hold the variable in its
private cache and keep reading the cached version, never noticing that
another core changed the memory location. What you need is atomic
access. Only then can you reliably and portably use a variable as a
ready flag.
Standard C++ doesn't yet have atomic variables. But various thread
libraries offer them.

All that said, if you're on an x86, all the above doesn't mean much,
because the architecture's cache consistency model should force the
change to be detected pretty soon.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply CornedBee 11/10/2009 3:32:15 PM

Hei schrieb:
> Hi,
> 
> I am using g++ to compile my C++ code.
> 
> Here is the simplified code:
> 
> class A {
>      public:
>          void change();
>          void doSomething();
>      private:
>          volatile bool ready;
> }
> 
> A::A() : ready(false) {}
> 
> A::change() {
>      printf("changed!\n");
>      ready=true;
> }
> 
> A::doSomething() {
>      // the actual code is not an infinite loop but very close --
> doSomething is being called at very high frequency without a while
> loop.
>      while(true) {
>          if (ready) printf("it is ready\n");
>          else printf("it is not ready\n");
>      }
> }
> 
> One of the threads will call A.change(), and another thread will call
> A.doSomething().
> Sometimes, I have the following output:
> it is not ready
> it is not ready
> it is not ready
> changed!
> it is not ready
> it is not ready
> it is not ready
> it is not ready
> 
> And I let the program continue for few minutes.  It still prints "it
> is not ready".
> 
> Any idea?
> 

Volatile has nothing to do with threads (and ISO-C++ doesn't know
anything about threads until C++0x). You have to use a mutex to
synchronize the memory between your threads.


Lars

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Lars 11/10/2009 3:40:40 PM

On Nov 10, 5:03 am, "Chris Morley" <chris.mor...@lineone.net> wrote:
> > And I let the program continue for few minutes.  It still prints "it
> > is not ready".
>
> > Any idea?
>
> Are you sure your threads are accessing the _same_ instance of class A you
> are using and not that each thread is accessing it's own thread local copy?
>
> You could test this easily by adding printfs to display "this" pointer & see
> if they match!
>
> void A::change() {
>      printf("change this=%p\n", this);
>       printf("changed!\n");
>       ready=true;
>
> }
>
> void A::doSomething() {
>      printf("doSomething this=%p\n", this);
>       while(true) {
>                  if (ready) printf("it is ready\n");
>           else printf("it is not ready\n");
>       }
>
> }
>
> If they don't print equal then you are definately using different instances.
> If they do print equal I'd need more code to see what the problem is.
>
> Hope this helps.
>
> Chris

I will give it a try later.

I believe that it is the same instance because if I restart the
program couple times, most the time, it works fine.  Hence, I believe
that it is some racing condition...or I mis-interpret "volatile".

Thanks.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Hei 11/10/2009 3:40:40 PM

On Nov 10, 8:28 am, Hei <hchan1...@gmail.com> wrote:
>          volatile bool ready;
[...
> One of the threads will call A.change(), and another thread will call
> A.doSomething().

Judging from the subject of your article and the mention of threads
you seem to assume that volatile has anything to do with threading. In
C++ it has not. The volatile keyword merely indicates that the
*compiler* should not optimize accesses to the corresponding object in
any shape. That is, the compiler will diligently put in the
appropriate read and write instructions to access the data. However,
the CPU will see that there is no synchronization directive and decide
that it doesn't need to reread or flush the cache and hence never
notice the change. Well, maybe it will notice the change at some
point, maybe it will not.

The purpose of the volatile keyword is mainly to deal with changing
memory the CPU somehow knows is changing. For example, this may apply
to memory mapped I/O hardware: the CPU will be vary careful not to
cache this. Since the compiler was careful to do what the code says
rather than trying to be smart, this will just work nicely.

When you want to communicate data between multiple threads you always
need some form of synchronization. This can be as basic as
strategically positioned memory barriers but something is needed. I
understand that other languages use e.g. 'volatile int' for things the
upcoming C++ standard will call 'std::atomic<int>' but this has not
relevance whatsoever how things in C++ are done: neither the current C+
+ standard nor the upcoming C++ standard will make any guarantees with
respect to the use of 'volatile' and threading. You may have found
that in the past sprinkling 'volatile' keywords over the code somehow
helped but this was mostly [bad] luck.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply dietmar_kuehl 11/10/2009 11:13:55 PM

On 11月10日, 下午1時32分, CornedBee <wasti.r...@gmx.net> wrote:
> On Nov 10, 9:28 am, Hei <hchan1...@gmail.com> wrote:
>
>
>
> > Hi,
> >          volatilebool ready;
>
> > A::A() : ready(false) {}
>
> > A::change() {
> >      printf("changed!\n");
> >      ready=true;
>
> > }
>
> > A::doSomething() {
> >      // the actual code is not an infinite loop but very close --
> > doSomething is being called at very high frequency without a while
> > loop.
> >      while(true) {
> >          if (ready) printf("it is ready\n");
> >          else printf("it is not ready\n");
> >      }
>
> > }
>
> > One of the threads will call A.change(), and another thread will call
> > A.doSomething().
>
> The semantics ofvolatileare very specific, and they are intended to
> read and write special memory locations (e.g. memory-mapped I/O
> registers of periphery), not for thread communication.Volatileforces
> the compiler to assume that the variable can change unexpectedly, that
> simply writing or even reading it can have side effects, and thus to
> never lift it to a register or reorder/omit accesses.Volatiledoes not force the CPU(s) to do anything, though. You're
> accessing a simple variable, an ordinary memory location. The CPU,
> unlike the compiler, isn't fooled by you - it knows that no periphery
> is going to change this location. Any core therefore can, depending on
> the architecture's cache consistency model, hold the variable in its
> private cache and keep reading the cached version, never noticing that
> another core changed the memory location. What you need is atomic
> access. Only then can you reliably and portably use a variable as a
> ready flag.
> Standard C++ doesn't yet have atomic variables. But various thread
> libraries offer them.
>
> All that said, if you're on an x86, all the above doesn't mean much,
> because the architecture's cache consistency model should force the
> change to be detected pretty soon.

{ edits: quoted banner removed. please don't quote the banner. -mod }

I understand the part that "volatile" isn't a replacement for a
synchronization block.  I don't know anything about the
"architecture's cache consistency model"...but I am running my program
on a x86_64 machine.

My original idea is to make the compiler not to optimize the code by
caching my variable in a register.  I am okay that in runtime, the
core takes several sec to detect that the volatile variable has been
changed.

I was trying to avoid using mutex/lock to save some micro sec because
doSomething() is called very frequently.

So it sounds like my CPU isn't able to detect the change?


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Hei 11/10/2009 11:18:59 PM

On 11月10日, 下午9時13分, "dietmar_ku...@yahoo.com"
<dietmar.ku...@gmail.com> wrote:
> On Nov 10, 8:28 am, Hei <hchan1...@gmail.com> wrote:
>
> >          volatilebool ready;
> [...
> > One of the threads will call A.change(), and another thread will call
> > A.doSomething().
>
> Judging from the subject of your article and the mention of threads
> you seem to assume thatvolatilehas anything to do with threading. In
> C++ it has not. Thevolatilekeyword merely indicates that the
> *compiler* should not optimize accesses to the corresponding object in
> any shape. That is, the compiler will diligently put in the
> appropriate read and write instructions to access the data. However,
> the CPU will see that there is no synchronization directive and decide
> that it doesn't need to reread or flush the cache and hence never
> notice the change. Well, maybe it will notice the change at some
> point, maybe it will not.
>
> The purpose of thevolatilekeyword is mainly to deal with changing
> memory the CPU somehow knows is changing. For example, this may apply
> to memory mapped I/O hardware: the CPU will be vary careful not to
> cache this. Since the compiler was careful to do what the code says
> rather than trying to be smart, this will just work nicely.
>
> When you want to communicate data between multiple threads you always
> need some form of synchronization. This can be as basic as
> strategically positioned memory barriers but something is needed. I
> understand that other languages use e.g. 'volatileint' for things the
> upcoming C++ standard will call 'std::atomic<int>' but this has not
> relevance whatsoever how things in C++ are done: neither the current C+
> + standard nor the upcoming C++ standard will make any guarantees with
> respect to the use of 'volatile' and threading. You may have found
> that in the past sprinkling 'volatile' keywords over the code somehow
> helped but this was mostly [bad] luck.
>

My confusion came after I read this article: http://www.ddj.com/cpp/184403766

I thought volatile made the compiler not to cache the variable in a
register, and so each thread would get a most updated copy.

If I understand all the post correctly, even with volatile, a variable
can be cached in a CPU's cache, and CPU somehow can figure when to
flush if the variable is changed...such change has nothing to do with
threads at all?


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Hei 11/11/2009 1:24:39 PM

Hi,

> I believe that it is the same instance because if I restart the
> program couple times, most the time, it works fine.  Hence, I believe
> that it is some racing condition...or I mis-interpret "volatile".

There is new information here that it work most of the time! I assumed from
your original post that it was always broken. I'd also say then you have
some race condition.

Without more code it is difficult to suggest something concrete but I'd be
suspicious obviously of any code that writes to the bool. If that is only
change() & the constructor then are you sure the object is _always_
constructed before change() is called? Is it a static? Is it stack/heap
allocated and before _or_ after you fork the new threads... stick a printf
in the constructor. (i.e. is it possible you get the sequnce a.change();
a(); a.soSomethign()) Try wasting some time prior to the change() call so
burn so cycles in a loop or Sleep() (Windows or *nix equivalent) for 1s &
see what happens. I'm sure you have searched for accidental writes to ready.
Does it always work if you set the affinity to a single core? Try setting
ready to true in the constructor, does it print ready all the time as
expected or sometimes not ready?? Is ready only ever _written_ to in 1
thread or more?

Anyway, if you can force a change of behaviour (broken always or fixed
always) it should give you an idea where your problem actually lies.

If it is a synchronisation problem then either construct the A before going
into the threads or if that isn't possible you need to synchronise the
start - I'd suggest you use OS functions (e.g. WaitForSingleObject on
Windows) as they can freeze thread execution while they wait. Also OS is
easier than rolling your own sync.

Chris


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Chris 11/11/2009 1:29:01 PM

dietmar_kuehl@yahoo.com wrote:
> Judging from the subject of your article and the mention of threads
> you seem to assume that volatile has anything to do with threading.
> In C++ it has not.

Mark Rosewater, in his many columns about designing the trading
card game Magic The Gathering, often writes that one of the worst
things a game designer can do is to confound the expectations of
players as to how something works. Here's a sample column.
<http://www.wizards.com/magic/magazine/article.aspx?x=mtgcom/daily/mr333>

Given that so many people assume that volatile data and multiple
threads work together as a simple form of synchronization, perhaps
they should.

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Hyman 11/11/2009 7:02:36 PM

On 10 Nov, 21:30, Pete Becker <p...@versatilecoding.com> wrote:
> Hei wrote:
>
> > And I let the program continue for few minutes.  It still prints "it
> > is not ready".
>
> > Any idea?
>
> Does the compiler's documentation tell you that this will work? The
> language definition does not require volatile to impose synchronization
> on a variable that's accessed from multiple threads. If one thread is
> running on one CPU and the other thread on another CPU, writing from one
> thread writes to that CPU's cache; the other CPU has its own cache, and
> won't see that change until the write is flushed to main memory and the
> previously read value is replaced from main memory. To make that happen,
> you need synchronization; typically through a mutex or a condition variable.

This would be a good answer except for the ouput.
The two threads show interleaved writes to a stdout. This is either
unsupported and he just got lucky or the I/O susbsystem is protecting
itself with mutexes hence I am leaning towards the idea that the OP
hasn't actually done what he says that he has done.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Nick 11/11/2009 7:04:01 PM

Hyman Rosen wrote:
> dietmar_kuehl@yahoo.com wrote:
>> Judging from the subject of your article and the mention of threads
>> you seem to assume that volatile has anything to do with threading.
>> In C++ it has not.
>
> Mark Rosewater, in his many columns about designing the trading
> card game Magic The Gathering, often writes that one of the worst
> things a game designer can do is to confound the expectations of
> players as to how something works. Here's a sample column.
> <http://www.wizards.com/magic/magazine/article.aspx?x=mtgcom/daily/mr333>
>
> Given that so many people assume that volatile data and multiple
> threads work together as a simple form of synchronization, perhaps
> they should.

They do on some systems (as an extension).

It would be EXTREMELY expensive on other systems, where volatile is 
actually used as originally intended - for accessing memory mapped 
devices. Would you like a 128-way Itanium system do invalidate all 
on-chip caches, just in case?


Bo Persson



-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Bo 11/12/2009 8:19:28 PM

"Hei" <hchan1980@gmail.com>

> My confusion came after I read this article: 
> http://www.ddj.com/cpp/184403766

Did you actually read it beyond the title?
It is about supplementing the code using sync with type system checks.

It neve claims volatile would be a replacement to using mutex and locking.

> I thought volatile made the compiler not to cache the variable in a
> register, and so each thread would get a most updated copy.

Then why class Counter in the article has that Mutex? And the other shown 
classes?

> If I understand all the post correctly, even with volatile, a variable
> can be cached in a CPU's cache, and CPU somehow can figure when to
> flush if the variable is changed...such change has nothing to do with
> threads at all?

In short, volatile has little to o with threading itself.

http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/

AA just uses it as MAGIC to detect imprer  access to a shared variable right 
at compare time.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Balog 11/16/2009 3:05:03 PM

Balog Pal wrote:
> (...)
> In short, volatile has little to o with threading itself.
> 
> http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/ 
> 

I would like to highlight one point from the article:

[quote volatile-almost-useless-for-multi-threaded-programming]
Now consider issue (2). Sometimes programmers think of volatile as
turning off optimization of volatile accesses. That's largely true in
practice. But that's only the volatile accesses, not the non-volatile
ones. Consider this fragment:

     volatile int Ready;
     int Message[100];
     void foo( int i ) {
         Message[i/10] = 42;
         Ready = 1;
     }
It's trying to do something very reasonable in multi-threaded
programming: write a message and then send it to another thread. The
other thread will wait until Ready becomes non-zero and then read
Message. Try compiling this with "gcc -O2 -S" using gcc 4.0, or icc.
Both will do the store to Ready first, so it can be overlapped with the
computation of i/10. The reordering is not a compiler bug. It's an
aggressive optimizer doing its job.

[/quote]

I personally never thought of this problem -- guess I'll have to do
another grep on our codebase for volatile.
Just another point on the list to check before I can enable
optimizations in the release build. *Sigh* :)

br,
Martin

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Martin 11/17/2009 7:48:09 AM

On Nov 11, 11:24 am, Hei <hchan1...@gmail.com> wrote:
> My confusion came after I read this article:http://www.ddj.com/cpp/184403766
>
> I thought volatile made the compiler not to cache the variable in a
> register, and so each thread would get a most updated copy.
>
> If I understand all the post correctly, even with volatile, a variable
> can be cached in a CPU's cache, and CPU somehow can figure when to
> flush if the variable is changed...such change has nothing to do with
> threads at all?

Again, as others else-thread have mentioned, volatile was intended for
memory mapped IO, (and signal handlers, and communication between
setjump and longjump (sp)). The article http://www.ddj.com/cpp/184403766
is simply wrong. Very wrong. For a full description on why volatile is
useless in C++ as a portable threading construct, I point you to my
favorite (and correct) paper on the subject:

C++ and the Perils of Double-Checked Locking
http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf

The short version is that most compiler writers have decided that they
can break the "as if" rule between threads without correct
synchronization. The standard doesn't mention threads, so it's not
like it's breaking the standard. It's also the correct decision in
terms of the spirit and intent of the C++ standard (don't pay for what
you don't use, cost competitive with assembly, volatile is for memory
mapped IO).


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Joshua 11/17/2009 3:01:49 PM

On Nov 16, 1:05 pm, "Balog Pal" <p...@lib.hu> wrote:
> "Hei" <hchan1...@gmail.com>
> > My confusion came after I read this article:
> >http://www.ddj.com/cpp/184403766
>
> Did you actually read it beyond the title?

The better question is did \you\ actually read it beyond the title.

> It is about supplementing the code using sync with type system checks.
> It neve claims volatile would be a replacement to using mutex and locking.

Yes, it does.

Quoting ddj article
> Although both C and C++ Standards are conspicuously silent when it comes to threads, they do make a little concession to multithreading, in the form of the volatile keyword.

> Just like its better-known counterpart const, volatile is a type modifier. It's intended to be used in conjunction with variables that are accessed and modified in different threads. Basically, without volatile, either writing multithreaded programs becomes impossible, or the compiler wastes vast optimization opportunities. An explanation is in order.

The article goes on to suggest that the following is a
"correct" (albeit inefficient and slow), condition variable in multi-
threaded situations:

class Gadget
{
public:
     void Wait()
     {    while (!flag_)
             Sleep(1000); // sleeps for 1000 milliseconds
     }
     void Wakeup() { flag_ = true; }
     ...
private:
     volatile bool flag_;
};

Quote ddj article (in the context of flag_ not being volatile):
> Suppose the compiler figures out that Sleep(1000) is a call into an external library that cannot possibly modify the member variable flag_. Then the compiler concludes that it can cache flag_ in a register and use that register instead of accessing the slower on-board memory. This is an excellent optimization for single-threaded code, but in this case, it harms correctness: after you call Wait for some Gadget object, although another thread calls Wakeup, Wait will loop forever. This is because the change of flag_ will not be reflected in the register that caches flag_. The optimization is too ... optimistic. Caching variables in registers is a very valuable optimization that applies most of the time, so it would be a pity to waste it. C and C++ give you the chance to explicitly disable such caching. If you use the volatile modifier on a variable, the compiler won't cache that variable in registers � each access will hit the actual memory location of that variable. So all y
!
  ou have to do to make Gadget's Wait/Wakeup combo work is to qualify flag_ appropriately:
[Insert code fragment with volatile flag_]

That piece of code when Wait and Wakeup are called from different
threads, despite whatever volatile qualification, is not correct
according to the C++ standard (as it doesn't mention threads). If it
was correct, that would be against the spirit of the C and C++
standard: (1- Volatile is for memory mapped IO, signal handlers, and
setjump longjump (sp). 2- Cost competitive with assembly. 3- Don't pay
for what you don't use.). It will not be correct in C++0x, which
includes descriptions of threading. Finally, according to the standard
threading library POSIX, it's actually wrong. (However, using the
other standard threading library, win32, the code fragment may be
correct with volatile. Go find a microsoft newsgroup or use the msdn
webpages for further details.)


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Joshua 11/17/2009 8:13:37 PM

{ Top-posting converted to bottom-posting by mod.
  Please follow the convention in this group. -mod }

On Tuesday, November 17, 2009 6:13:37 PM UTC-8, Joshua Maurice wrote:
> On Nov 16, 1:05 pm, "Balog Pal" <p...@lib.hu> wrote:
> > "Hei" <hchan1...@gmail.com>
> > > My confusion came after I read this article:
> > >http://www.ddj.com/cpp/184403766
> >
> > Did you actually read it beyond the title?
> 
> The better question is did \you\ actually read it beyond the title.
> 
> > It is about supplementing the code using sync with type system checks.
> > It neve claims volatile would be a replacement to using mutex and locking.
> 
> Yes, it does.
> 
> Quoting ddj article
> > Although both C and C++ Standards are conspicuously silent when it comes to threads, they do make a little concession to multithreading, in the form of the volatile keyword.
> 
> > Just like its better-known counterpart const, volatile is a type modifier. It's intended to be used in conjunction with variables that are accessed and modified in different threads. Basically, without volatile, either writing multithreaded programs becomes impossible, or the compiler wastes vast optimization opportunities. An explanation is in order.
> 
> The article goes on to suggest that the following is a
> "correct" (albeit inefficient and slow), condition variable in multi-
> threaded situations:
> 
> class Gadget
> {
> public:
>      void Wait()
>      {    while (!flag_)
>              Sleep(1000); // sleeps for 1000 milliseconds
>      }
>      void Wakeup() { flag_ = true; }
>      ...
> private:
>      volatile bool flag_;
> };
> 
> Quote ddj article (in the context of flag_ not being volatile):
> > Suppose the compiler figures out that Sleep(1000) is a call into an external library that cannot possibly modify the member variable flag_. Then the compiler concludes that it can cache flag_ in a register and use that register instead of accessing the slower on-board memory. This is an excellent optimization for single-threaded code, but in this case, it harms correctness: after you call Wait for some Gadget object, although another thread calls Wakeup, Wait will loop forever. This is because the change of flag_ will not be reflected in the register that caches flag_. The optimization is too ... optimistic. Caching variables in registers is a very valuable optimization that applies most of the time, so it would be a pity to waste it. C and C++ give you the chance to explicitly disable such caching. If you use the volatile modifier on a variable, the compiler won't cache that variable in registers � each access will hit the actual memory location of that variable. So al
 l
>  you have to do to make Gadget's Wait/Wakeup combo work is to qualify flag_ appropriately:
> [Insert code fragment with volatile flag_]
> 
> That piece of code when Wait and Wakeup are called from different
> threads, despite whatever volatile qualification, is not correct
> according to the C++ standard (as it doesn't mention threads). If it
> was correct, that would be against the spirit of the C and C++
> standard: (1- Volatile is for memory mapped IO, signal handlers, and
> setjump longjump (sp). 2- Cost competitive with assembly. 3- Don't pay
> for what you don't use.). It will not be correct in C++0x, which
> includes descriptions of threading. Finally, according to the standard
> threading library POSIX, it's actually wrong. (However, using the
> other standard threading library, win32, the code fragment may be
> correct with volatile. Go find a microsoft newsgroup or use the msdn
> webpages for further details.)

Sorry to bring back this old thread.

As most of you pointed out, C++ Standard (before C11) doesn't know
anything about thread; hence, volatile has nothing to do with thread.

I just want to understand whether this statement from Modern C++ Design
(by Andrei Alexandrescu) is wrong:
"C++ provides the volatile type modifier, with which you should qualify
each variable that you share with multiple threads."

Although it doesn't explicitly suggest volatile do something about
multithreading, it seems to me that it implicitly suggests so.

If not, how should I interpret the statement?

Thanks in advance.

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply hchan1980 11/2/2012 6:25:16 PM

On 2012-11-02 18:25:16 +0000, hchan1980@googlemail.com said:

>
> I just want to understand whether this statement from Modern C++
> Design (by Andrei Alexandrescu) is wrong:
> "C++ provides the volatile type modifier, with which you should
> qualify each variable that you share with multiple threads."
>
> Although it doesn't explicitly suggest volatile do something about
> multithreading, it seems to me that it implicitly suggests so.
>
> If not, how should I interpret the statement?
>

Interpret it as wrong.

-- 
   Pete


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Pete 11/3/2012 3:19:39 PM
comp.lang.c++.moderated 10595 articles. 7 followers. Post

19 Replies
150 Views

Similar Articles

[PageSpeed] 3

  • Permalink
  • submit to reddit
  • Email
  • Follow


Reply:

Similar Artilces:

Clarification on the applicability of compile-time optimization to a struct variable which encompasses a mixture of fields declared as volatile and non-volatile individually
#include <stdio.h> struct InterruptData { int numberOfInterrupts; volatile int timer; int numberOfTimesInterruptsMasked; } InterruptMonitor; /* * Interrupt handler code. */ int main(void) { InterruptMonitor = InterruptMonitor; printf("\n LOG - InterruptMonitor.numberOfInterrupts : %d \n", InterruptMonitor.numberOfInterrupts); printf("\n LOG - InterruptMonitor.timer : %d \n", InterruptMonitor.timer); printf...

How can we ignore about defconstant when compiling
Hi everybody, I am using SBCL in Emacs + Slime. I see a very strangle issue that there is an warning when I compile the file in which I define a constant. The constant BIOLOGICAL-DATA-MODEL:+META-TOOL-FILE+ is being redefined (from "/home/nvntung/stage/project/DATA/mito-muscle-R10Rev-2.dat" to "/home/nvntung/stage/project/DATA/mito-muscle-R10Rev-2.dat") [Condition of type DEFCONSTANT-UNEQL] Is there anyone has ever met this issue? On 17 Aug., 16:17, Elvis Nguyen <nvnt...@gmail.com> wrote: > Hi everybody, > > I am using SBCL in Emacs + Slime. I see a ve...

Fujitsu compiler ignoring code?
First I'd like to thank everyone who helped with my CBL_ routines problem. That's all solved now, many thanks. I now have a different, very odd problem. The following paragraph is called from an EVALUATE within a PERFORM UNTIL loop: 400-JOINT-DEBTOR-INFO. *> F5 IF DEBT-JOINT-DEBTOR = SPACES THEN MOVE "No Joint Debtor to view." TO COLLECT-HELP-LINE ELSE CLOSE DEBTOR-FILE *> opened elsewhere <INITIALIZE PARAMETERS> PERFORM SET-LOCAL-FOLDER *> Essentially just a wr...

Non-volatile compiler optimizations
Hello, I'm trying to understand volatile. I have written trivial code where a variable is tested to decide whether to break early out of a loop. I've considered 4 different cases. auto variable static with function scope static with file scope external linkage AFAIU, since the abstract machine model is single threaded, if a variable is not volatile, then its value cannot change inside the loop. (Signals might be an exception?) Thus, in every case, the compiler is allowed to remove the test, because it may assume that the variable cannot change. I tested with gcc...

visibility attribute ignored in compilation
Given the following function prototype: void dummy(void) __attribute__ ((visibility ("internal"))); When I compile I get the following compiler message: warning: `visibility' attribute directive ignored I have been unable to much information about this warning. Is there a compiler flag/option that I need to use? Thanks, jenn jcellis@us.ibm.com ================================== Poster's IP address: 24.95.136.71 Posted via http://nodevice.com Linux Programmer's Site 24.95.136.71 [JennTPF] writes: > void dummy(void) __attribute__ ((visibility ("internal&q...

Compilers should have an option to ignore unknown flags?
I'm sure I'm not the first or last to try to compile a bit of open-source software with a Sun compiler and find it stop because some idiot developer has added -Wall or some other gcc specific flag and totally ignores what you set CFLAGS too. I've reported this as a bug on the GNU Common Lisp http://savannah.gnu.org/bugs/index.php?func=detailitem&item_id=16697 where I set CFLAGS to -fast -fsimple=1, but the the configure script turns that into -fast -fsimple=1 -Wall -DVOL=volatile -fsigned-char -O3 -fomit-frame-pointer So needless to say the Sun compiler (Studio 11) st...

Weird C++ Compiler Ignores Errors
C++ Compiler looks weird. It will succeed to compile if your source code has some errors. I wrote an example of generic class. I commented Errors.Print() in the main function body. Errors.Print() has two variables _x and _y, but class definition only shows two variables x and y. Go ahead and try to compile. Read my comments below. template< typename T > class IgnoreErrors { public: IgnoreErrors() : x( 1 ), y( 2 ) {} ~IgnoreErrors() {} void Print(); T x; T y; }; template< typename T > void IgnoreErrors< T >::Print() { _x =3D 5; _y =3D ...

MATLAB compiler ignoring escape characters
So, I have a program which performs a large number of statistical calculations and prints the results to a text file. This works fine when the m-file is run in MATLAB, so I've attempted to make a windows .exe, which has worked perfectly, aside from the fact that my text file output now consists of one *very* long line of text! The /t characters appear to be executing but the /n newline commands appear to be ignored. This is a slight cause for consternation and I was wondering if anyone else had come across this problem? ...

'const' ignored when compiling in linux
This: #include <vector> class Image2D { public: void test() const { con.push_back(234); } private: std::vector<int> con; }; int main(){ Image2D img; // test(); return 0; } compiles fine on ubuntu linux using gcc 4.4.1. But I get an error when I try to compile the same code in Visual studio 2008. I can fix this error in VS if I declare: mutable std::vector<int> con; But why does the gcc compiler not complain when I modify a member in a const function? none ha scritto: > #include <vector> > class Image2D {...

[GNAT] compiler options ignored for sources from ADA_INCLUDE_PATH
The title says most, except it is through a GNAT project (.gpr). More precisely, all compiled files land into the directory specified in for Object_Dir use ...; That's OK. But the compiler options specified in package Compiler is for Default_Switches ("ada") use (...); end Compiler; are applied only to the sources found in for Source_Dirs use (...); and not to sources found in ADA_INCLUDE_PATH. Bug ? Feature ? Any way to have the compiler options applied to all sources ? _________________________ Gautier's Ada programming http://gautiersblog.b...

Compilling error when using --disable-volatile-data
Hello there, I found a problem when you configure with --disable-volatile-data ---------------------------------- /home/avd/wksp/buildroot/output/host/usr/bin/arm-buildroot-linux-uclibcgnueabi-gcc -DHAVE_CONFIG_H -I. -I.. -I../term -I../term -DBINDIR=\"/usr/bin\" -DX11_DRIVER_DIR=\"/usr/libexec/gnuplot/4.6\" -DQT_DRIVER_DIR=\"/usr/libexec/gnuplot/4.6\" -DGNUPLOT_SHARE_DIR=\"/usr/share/gnuplot/4.6\" -DGNUPLOT_PS_DIR=\"/usr/share/gnuplot/4.6/PostScript\" -DGNUPLOT_JS_DIR=\"/usr/share/gnuplot/4.6/js\" -DGNUPLOT_LU...

mpss.so.1 and -xpagesize compiler options totally ignored...
Hi! ---- Is there a reason why an application just allocates 8k pages for both stack and heap even when I set the matching env vars for mpss.so.1 to 512K or compile the application with -xpagesize=512K ? What are the exact rules within the kernel to choose/not choose larger-than-8k pages for heap and stack ? Can I _force_ the usage of larger page sizes somehow ? ---- Bye, Roland -- __ . . __ (o.\ \/ /.o) roland.mainz@nrubsig.org \__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer /O /==\ O\ TEL +49 641 7950090 (;O/ \/ \O;) > ---- > > I...

Netbeans 4.0 ignores -source compiler option
I could not get Netbeans 4.0 to process the -source 1.4 compiler option as entered in the project properties. There were similar posts here with no useful advice. Specifically getting a lot of messages trying to add objects to collections classes in an un-generic way. Just guessing, it is necessary to specify -source 1.5 to javac so they just do that anyway. Downloaded netbeans 4.1 today and along with restructuring the properties dialog there is a new handy Source Level combobox which solves the problem. Is there a way in Netbeans 4.0. The truth is out there I know. ...

Quartus II 2.2 smart compile ignoring .mif
I'm having a very odd problem... Quartus II (2.2) has started ignoring ..mif file changes on me when doing "smart compile", which requires me to sit for 20 minutes and recompile the whole design for a simple memory change. The really weird part is that this is new behaviour -- I have one project on which this works beautifully and it was a major assistance debugging that design, but on a different (somewhat larger) project, it doesn't work at all -- Quartus seems to just ignore the .mif file changes and happily produces bitstream files with all the old memory contents. Is t...

pgsql-server: Check for ignored thread compiler options to reduce
Log Message: ----------- Check for ignored thread compiler options to reduce compiler noise. Modified Files: -------------- pgsql-server: configure (r1.391 -> r1.392) (http://developer.postgresql.org/cvsweb.cgi/pgsql-server/configure.diff?r1=1.391&r2=1.392) pgsql-server/config: acx_pthread.m4 (r1.6 -> r1.7) (http://developer.postgresql.org/cvsweb.cgi/pgsql-server/config/acx_pthread.m4.diff?r1=1.6&r2=1.7) ---------------------------(end of broadcast)--------------------------- TIP 2: you can get off all lists at once with the...

using values despite ignore declarations and compile 3rd return value
============================= http://www.lispworks.com/documentation/HyperSpec/Issues/iss065_w.htm: .... (b) Conditions of type WARNING may be signalled by the compiler... Examples: ... referencing a variable declared IGNORE ... ============================= http://www.lispworks.com/documentation/HyperSpec/Body/f_cmp.htm The tertiary value, failure-p, is false if no conditions of type error or warning (other than style-warning) were detected by the compiler, and true otherwise. ============================= this means that (compile nil (lambda (x) (declare (ignore x)) x)) should return #<...

Ignore locale for ctype functions isupper() islower() etc in a certain compilation unit
I want to set the locale, and use it in most of my application. However, in certain legacy compilation units I want the ctype functions to use the C (ASCII) locale--I want them to be insensitive to the locale. In particular, I am thinking of the functions: isalpha() isalnum() isgraph() isupper() islower() isspace() While it is simple enough to write my own version of these functions, I see in Linux /usr/include/ctype.h the macro __NO_CTYPE. It looks as if it might do this for me: // Ignore the locale #define __NO_CTYPE #inclu...

Sun Studio 10 C++ compiler ignoring the const char* operator. Bug or feature?
This happens on Solaris 10, with Sun Studio 10 or higher. Take aany class with overloaded const char*() and char*() operators. When compiled with Sun Studio 10 or higher the const operator seems to be ignored. The compiler does not produce any warnings. Simply swallows the code and resolves all calls to the non-const operator. Try compiling a sample program below. When compiled with Sun Studio 8 the const operator is invoked, as you'd expect. When compiled with Sun Studio 10 or higher, the non-const operator is invoked. #include <stdio.h> class HvfBolek { public: HvfBolek(); ...

Trying to fix 'warning: no compiler specified for language "Ada", ignoring all its sources'
I've gone through the gems 68 and 69 here: http://www.adacore.com/adaanswers/gems/gem-68/ http://www.adacore.com/adaanswers/gems/gem-69/ I was able to reproduce the examiner/simply/POGS results, but if I actually= try to compile the code from GPS, I get the message: gprbuild -d -P/Users/Dependable/Tools/Spark1/search/default.gpr default.gpr:1:09: warning: no compiler specified for language "Ada", igno= ring all its sources gprbuild: no sources to compile Similarly, if I try to compile just search.adb, I get: gprbuild -ws -c -u -P/Users/Dependable/Tools/Spark1...

[long] Cannot compile my assignment: "(W) Too many arguments are specified for the macro 'move'. The extra arguments are ignored." and more
Hi all, == Background info == I am good with Linux but an AIX and Unix C++ newbie. I am using the relatively modern VisualAge C++ Professional 5 on ancient AIX. The machine is old and there is no way I could get gcc onto it. uname -a gives: AIX castor 3 4 000097764C00. == Error messages == I am getting repeated errors like: "/usr/vacpp/include/iosfwd", line 129.38: 1540-0816 (W) Too many arguments are specified for the macro "move". The extra arguments are ignored. "/usr/include/curses.h", line 1068.9: 1540-0425 (I) "move" is defined on line 1068 of...

which compiler compiled?
Is there a way I can tell which compiler compiled an executable? I looked at the file with a hex editor and didn't see anything obvious. Lawrence "Lawrence" <just4me@nowhere.com> writes: > Is there a way I can tell which compiler compiled an executable? Yes with some compilers and some executable formats. E.g. on HP-UX for PA-RISC: $ aCC leak.C $ odump -compunit a.out ... 6 0 ANSI C++ leak.C /tmp ctcom options = -inst compiletime -diags 523 -inline_power 1 -longbranch 2 -unique_strings on -cachesize 256 B...

To compile or not to compile
Is there some benefit in compiling the apache source yourself? -- //Points ------------------------------------------------------------ http://underthebed.homeip.net ...

Compiled or not compiled
I need to distinguish between two situations: one when a Matlab function is run from Matlab command window and the other one when it is run in compiled mode. Any ideas how to do this? Thanks Tomy Duby "Tomy Duby" <tomy.duby@agilent.com> wrote in message news:idq8q8$85k$1@fred.mathworks.com... > I need to distinguish between two situations: one when a Matlab function > is run from Matlab command window and the other one when it is run in > compiled mode. > Any ideas how to do this? HELP ISDEPLOYED. -- Steve Lord slord@mathworks.com comp.s...

Compile or not compile?
There's something that sometimes in while it bores me a little bit. How do I know if I need to compile a function/procedure or it will be able to compile "on fly". At the beginning I thought this was related to the paths idl "knew", but this happens for two functions/routines in the same directory. Can someone tell when a function can be runned without be compile? Nuno Oliveira wrote: > There's something that sometimes in while it bores me a little bit. How > do I know if I need to compile a function/procedure or it will be able > to compile &quo...