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 10663 articles. 10 followers. Post

19 Replies
206 Views

Similar Articles

[PageSpeed] 26


  • Permalink
  • submit to reddit
  • Email
  • Follow


Reply:

Similar Artilces:

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 ...

Compiling Compiler
Hi there, I need some advice/opinion of the experts out there regarding compilers. I have sun cc compiler that supports 64 bit environment. Now, I compile ACK using this compiler.This should give a compiler that supports 64bit environment. Since the output files are in Solaris format, I compile the ACK source *once again* using the just compiled ACK compiler so that I get Minix object and binary files. Now my questions is that does this 2nd version of ACK be able to produce true 64bit code? Sanky wrote: > Hi there, > > I need some advice/opinion of the experts out there regarding...

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...

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

compiling Qt .... compiling Qt ....compiling Qt.... compiling Qt
I got myself new kernel from kernel.org... make xconfig needs Qt (new system). So I got new Qt source this afternoon. It is still compiling.... Who said MS is bloat has not done this. What does Qt do? Dunno, how about xforms for xconfig? On Thu, 02 Feb 2006 19:18:09 +0000, Jan Panteltje wrote: > Dunno, how about xforms for xconfig? Why not curses based? menuform -- Hilsen/Regards Michael Rasmussen http://keyserver.veridis.com:11371/pks/lookup?op=get&search=0xE3E80917 On a sunny day (Thu, 02 Feb 2006 21:55:33 +0100) it happened Michael Rasmussen <mir@miras.or...

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...

program that compiles in C compiler but not in C++ compiler
Hi, I need a small program that compiles in C compiler but not in C++ compiler. Thx in advans, Karthik Balaguru KBG <karthik.balaguru@lntinfotech.com> wrote: > I need a small program that compiles in C compiler but not in C++ > compiler. No problem, just send $10 to paypal@zevv.nl and I'll do your homework for you. -- :wq ^X^Cy^K^X^C^C^C^C KBG said: > Hi, > > I need a small program that compiles in C compiler but not in C++ > compiler. Can you think of any syntactic differences between C and C++? For example, what about keywords? They are very, very sen...

Writing a compiler compiler
Hello, Firstly, let it be known that I am quite new to the subject of parser generators, and having written only simple parsers for frivoulous grammars by hand have little experience. My objective is thus - to create a parser generator that will eventually generate a parser for a dynamic language. However, my undestanding of different parser types and distinctions between is minimal; but as the web is a good enough resourse please assume my knowledge of those areas. The target for this parser generator would be a language similar to C#, and I have found Jay (a yacc clone to C# and Java). Th...

Compiling with the eclipse compiler
Hey all,I have a weird problem (at least it's weird to me).I have a big project that I need to compile through ant with eclipse'scompiler.In the build.xml my compile target looks like this : <target name="compile" depends="release-settings, init" description="compiles everything from source"> <echo message="Compiling with debug = ${build.debug}"/> <depend srcdir="${src.dir}" destdir="${class.dir}" cache="${dependencies.dir}" closure="true"/> <javac srcdir=...

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...

Meta4... a compiler-compiler
in the csa2 gmail account... description is very interesting. in the Pidgin for Apple II/Merlin/6502 message Rich ...

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...

compiling on different compilers
I am working on a set of functions that involve dynamic memory allocation. I started working with gcc and then moved to Pacific C. The reason was that my only access to gcc was through an ssh connection that I did not have access to all the time, so I got Pacific so I could work on my home windows computer. Then I moved back to gcc, which saved me from some major mistakes. Somehow Pacific C was letting me get away with stuff that was completely wrong. gcc immediately gave me segmentation errors until I got every last thing correct. Is gcc the best for catching mistakes? If not, which on...

which compiler was used to compile?
Is there a slick way to invent a constant in a program that tells you which compiler you used. I distribute both JET and JavaC versions of my code, and it helps to know on any error dump which version they were using. Right now I manually change a static final just before compiling. I thought there ought to be something less error prone. -- Canadian Mind Products, Roedy Green. Coaching, problem solving, economical contract programming. See http://mindprod.com/jgloss/jgloss.html for The Java Glossary. Roedy Green wrote: > Is there a slick way to invent a constant in a program that tell...

Problem to compile with g77 a program which was normally compiled with Absoft compiler
Hello, I get the following error messages when I try to compile a program with g77 somefile.f:(.text+0x93): undefined reference to `for_open' somefile.f:(.text+0xf4): undefined reference to `for_write_seq_fmt' somefile.f:(.text+0x128): undefined reference to `for_write_seq_fmt_xmit' somefile.f:(.text+0x454): undefined reference to `for_read_seq' Could you help me to fix this? I have posted more details about my actions on http://stackoverflow.com/questions/3365742/f77-problem-to-compile-with-g77-a-program-which-was-normally-compiled-with-absof Thank you On 30/07/2010 10:2...

Compiler mystery: Compiles classes that don't compile
Can someone please try and explain how this could even happen. I'm about to start fixing some bugs in a program for a client. They haven't really been that organised and just gave me some source code from somewhere, which may or may not be the version of the source code that was used to compile the version of the app that I am supposed to fix bugs in. Now to the problem. The code doesn't even compile. There's a file Container.java, which is missing heaps of methods (private ones I guess as they are only called from inside Container). I decompiled the actual application and whe...

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 {...