volatile is ignored by my compiler?

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
Hei
11/10/2009 2:28:56 AM
comp.lang.c++.moderated 10707 articles. 0 followers. allnor (8507) is leader. Post Follow

19 Replies
235 Views

Similar Articles

[PageSpeed] 57
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Pete
11/3/2012 3:19:39 PM
Reply:
Similar Artilces:

volatile
I have read about this qualifier in many books and have read things like "would not let the compiler optimize" "can be modified externally" etc. But I am not able to understand it well. Could someone give me a small example and explain the meaning and use of the volatile qualifier. TIA. -- main(){char s[40]="sbwjAeftqbnnfe/dpn!ps!CSbwjACjhgppu/dpn"; int i;for(i=0;i<39;putchar(s[i++]-1));return 0;} On Sun, 12 Oct 2003 22:46:05 +0530, Ravi wrote: > I have read about this qualifier in many books and have read > things like "would not let the compi...

HPUX kernel compile???
Hello, I have been assigned to perform a security review for a HPUX system which is in production. One thing I have noticed is that the system has a C compiler on the system. Since this is not a development system I suggested that it be removed. The sysadmin mentioned that it is required to perform kernel compilation, which caught me by surprise. I come from the Linux camp. (I do love all flavors of Unix). My understanding is that HPUX is a closed source operating system. Has HP opened it's source code to open source (like Solaris)? If not, then what type of kernel code is being c...

ide for shedskin python to c compiler
I have a beta ide that I stold for shed skin and bcx basic available. currently it is set up to compile just from one directory.. It is available http://dexrow.blogspot.com/2008/01/bcx-with-cr-editor.html It could use a much better script and I would be glad to hear suggestions. ...

Odd LabVIEW 8.20 compiler behaviour
I've a LabVOOP 8.20 project with very odd behaviour. When I open the project and close it immediately LV claims that the project has unsaved changes. When I use "Explain Changes" to view the changes, they are following: For three static method VIs belonging to three different classes (root, childA &amp; childB) the changes are - VI recompiled. - SubVI call(s) modified. For two classes (root &amp; childA) the changes are following - Name or location of items in the file system changed. - The private data control for this class changed. If I then select Save all, LabVIEW st...

ignore test PGP 1165128572.5 #232
igrnore. this is a testfile, please disregard ...

cross
Hi all, I am working on Mips32 -4Kc processor. when i cross-compile the C-code on linux using "mipsel-linux-gcc" toolchain and observe the listing (assembly) , it is not using the features of the Mips32 -4Kc instructions, but using only MIPS-I ISA instruction set. I even used "-Wa,-mips2 -Wa,-mips32 -Wa,-march=4Kc " option as: mipsel-linux-gcc -S -Wa,-mips2 -Wa,-mips32 -Wa,-march=4Kc main.c But i want to get my C-code get cross-compiled with all features of the Mips32 -4Kc instructions (like CLZ, CLO, MOVN, MOVZ, MADD MSUB ) for better performance. Can this be done?? b...

Using Table and ignoring all errors and warnings?
I would like to use Table function, but have it ignore any errors or warnings and skip that value if one is produced. Illustrative Example: Table[1/i, {i, -3, 2}] Power::infy: Infinite expression 1/0 encountered. >> {-(1/3), -(1/2), -1, ComplexInfinity, 1, 1/2} I would like the output to just be {-(1/3), -(1/2), -1, 1, 1/2} with no errors/warnings given as messages and the index that would produce a message to just be ignored. It's not just specific to 1/0 error, but any type of error or warning I want it to ignore it and skip to the next value; with the final output...

C++ template compile error on g++ 4.1.2
Can anyone explain to me why the following code doesn't compile (I stripped it down from a larger multi-file application). Is this a problem with the compiler or me :-): /* * Below is a example showing the problem I'm having trying to compile under * gcc 4.1.2 on Red Hat Enterprise Linux release 5.3 (Final). I get the * following compile errors: * * What am I doing wrong? * * test/TestCase.cpp:97: error: too few template-parameter-lists * test/TestCase.cpp:102: error: too few template-parameter-lists * * Mike */ #include <string> #include <iostre...

ignore funtiction?
Please help, this is due at 11:59 PM tonite. Thanks Write a program that reads a person's name from the keyboard in the format First Middle Last. It should then (1) print each of the names on a separate line and (2) print the person's initials on the fourth line. Assume that each person has exactly 3 names, that the first name begins in the first position on a line (there are no leading blanks) and that the names are separated from each other by a single blank. Do not use arrays in this assignment. SO far i gigured out only how to print out the initials, but i can't figure o...

please help compiling on sgi
trying to compile 5.0.27 on sgi irix 6.5. in looking at the source i am unable to see any reason for it to not compile. thanks for any help. my config line: CC=cc CXX=CC CFLAGS='-O1 -n32 -TARG:platform=IP30 -D_BSD_TYPES -D_BSD_TIME -woff 1184,1552 -DLANGUAGE_C -I/usr/include -L/lib32 -L/usr/lib32 -L/usr/lib' \ CXXFLAGS='-O1 -n32 -TARG:platform=IP30 -D_BSD_TYPES -D_BSD_TIME -woff 1184,1552 -DLANGUAGE_C -I/usr/include -L/lib32 -L/usr/lib32 -L/usr/lib' \ ../configure --prefix=/sw/mysql/5.0.27/sgi65 \ --with-low-memory --without-innodb \ --with-extra-charsets=complex --without-ser...

Re: Compile and arrays
----- Original Message ----- > From: "Eric Michielssen" <emichiel@eecs.umich.edu> > To: mathgroup@smc.vnet.net > Sent: Friday, November 26, 2010 4:30:06 AM > Subject: Compile and arrays > Compiled functions that act on subarrays of supplied arrays often run > very > slow. > > As an example, consider the following two routines "Ctest" (compiled) > and > "test" (standard mathematica). They do the same, namely extract the > first > row from matrices a and b, and add them. > > Ctest = Compile[{{a...

Volatile and code reordering
I believe the consensus of this group is that volatile does not protect against code reordering. But I am not convinced. The standard says that "accesses to volatile objects are evaluated strictly according to the rules of the abstract machine." A later note states "An implementation might define a one-to-one correspondence between abstract and actual semantics: at every sequence point, the values of the actual objects would agree with those specified by the abstract semantics. The keyword volatile would then be redundant." I would take the above to mean that it does guara...

New edition of "Basics of Compiler Design"
I have added a new chapter about analysis and optimisation to my book "Basics of Compiler Design", which you can download for free from my home page (gttp://www.diku.dk/~torbenm/Basics). The new chapter covers simple dataflow analysis, function-call optimisation, loop optimisation and specialisation. Torben Mogensen ...

Please Ignore
This is just a test message. ...

pwelch and Compiler
I have built a GUI that uses pwelch to generate PSD plots. When I run the GUI from MATLAB, I have no problems. But, when I compile it using MATLAB Compiler (R14 SP2) and try the same thing, I get the following errors: Warning: an error occurred while parsing class spectrum.abstractspecwwindow: Function 'findclass' is not defined for a first argument of class 'double'. Warning: an error occurred while parsing class spectrum.periodogram: Invalid superclass handle. Warning: an error occurred while parsing class spectrum.welch: Invalid superclass handle. Unable to create a class a...

(David Creelman) Wx for cross compiling on Linux ?
I don't usually chase SORBS bounces, but dave seems like a nice guy with the wrong isp, and this is useful general knowledge in any case that hasn't been explicitly mentioned for a while. Ron This message was created automatically by mail delivery software. A message that you sent could not be delivered to one or more of its recipients. This is a permanent error. The following address(es) failed: dave@geko.net.au SMTP error from remote mail server after RCPT TO:<dave@geko.net.au>: host mailstore.hotkey.net.au [202.138.0.43]: 553 Dynamic IP Addre...

Building a linked list at compile time using HLA
Hello out there, coming back to assembly programming after a loooong time I found HLA (High Level Assembly) and figured that it should make things a bit easier. However there was a show stopper right away: I need to build a linked list at compile time where the different elements may be of different length. (Background: I want to implement a Forth dialect and Forth's *words* - think functions - are chained this way.) In 'real' assembler one starts out with definitions like this (simplified): PREVCODE = . // init to current location // This macro will star...

Compile .c file as C++ source in MS Studio
Hello everyone, Can anybody help me how can I compile of my *.c files as c++? I see that by default MS Visual Studio compiles the *.c files assuming C source. How can I instruct the compiler to compile it as C++ source? Thanks in advance AR "AR John" wrote: > Hello everyone, > > Can anybody help me how can I compile of my *.c files as c++? I see > that by default MS Visual Studio compiles the *.c files assuming C > source. How can I instruct the compiler to compile it as C++ source? > > Thanks in advance > AR On MSVC 6 you can use the /Tp...

Newbie: Compiler needed
Hi all, If this NG is the wrong one, excuse me. I am thinking of learning C++ to write my own OS (maybe, one day, etc...). What is a really good compiler for me to buy ? TIA. Steve Steve H. posted: > Hi all, > If this NG is the wrong one, excuse me. I am thinking of learning C++ > to write my own OS (maybe, one day, etc...). What is a really good > compiler for me to buy ? TIA. > Steve > Depends on the CPU you're aiming for. If you're aiming for the Intel Pentium family, then probably your best bet is to go to Intel. -JKop On Fri, 23 Jul 2004 08:37:41 -0700...

volatile or what? ...
I have Linux Mandrake 9.0, and work in GNU C++ Compiler. I have a network server divided into two parts: one that handles the existing connections and serves them ("SERVER1"), and the second one that waits for new connections ("SERVER2"). When the Server2 reads call from a new client, it establishes a new socket-connection for it, sends a SIGUSR1 signal (!) to Server1, and then delivers this new connection to it (to Server1). Server1 is the main() function, and the Server2 is a p_thread created from within the main(), at the very beginning. They communicate partly over a f...

hpux c++ compilers
Hi, I have a HP system loaded with 11i and need a c++ compiler. The compiler is HP aC++ B3910B A.03.30 . Does anyone know where and how to get that compiler? thanks a lot. David david (kuoweiwang@yahoo.com) wrote: : I have a HP system loaded with 11i and need a C++ compiler. The : compiler is HP aC++ B3910B A.03.30. Does anyone know where and how to : get that compiler? You can purchase the latest aC++ compiler on the web. http://www.hp.com/go/cpp The latest version will be A.03.50 shortly: http://h21007.www2.hp.com/dspp/tech/tech_TechSoftwareDetailPage_IDX/1,1703,1743,00.html A.03.30 wa...

severe compile problems with wine -> out of memory
Hi! When I try to compile wine the following error occurs: make[2]: Leaving directory `/tmp/wine-20050310/programs/winepath' make[2]: Entering directory `/tmp/wine-20050310/programs/winetest' .../../tools/winegcc/winegcc -B../../tools/winebuild -mconsole gui.o main.o send.o util.o winetest.exe.dbg.o winetest.res -o winetest.exe.so -L../../dlls -lcomctl32 -luser32 -lgdi32 -lwsock32 -L../../libs/wine -lwine -L../../libs/port -lwine_port If I don't hurry up pressing Ctrl+C the compiler will cause the system to (almost) crash. What you can see is that the hard drive ...

problem compiling mono
Hi, I have installed a Debian Sarge system and downloaded mono-1.0.5.tar.,gz. While running ./configure --prefix=/usr/local I get the error configure: error: Library requirements (glib-2.0 >= 1.3.11) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them. But I have libglib 2.0 installed: hk@debian:~/projects/mono-1.0.5$ ls -F /usr/lib/libglib* /usr/lib/libglib-1.2.so.0@ /usr/lib/libglib-2.0.so.0@ /usr/lib/libglib-1.2.so.0.0.10 /usr/lib/libglib-2.0.so.0.400.1 How can I get mono ...

ssax-sxml to ignore namespaces
I'm using ssax-sxlm to parse Maven's pom.xml files. Some will have namespac= es and the rest just a plain project tag. I'd like to get the sxml with the= simple local names even when the namespaces are present but haven't figure= d out how to use ssax-sxml for doing that. Alternatively, I defined two aliases, for ns and xsi, but can't get the sxp= ath function to recognize the aliases (I get "unknown namespace ns") using = a string path like "//project/dependencies/*". ...

Library compiler without a license?
I generated some RAM models in .lib format then converted them into ..db. However, I have library compiler here, .db files were generated with a warning "The LIbrary OCmpiler is not enabled, The cell functionality is ignored." With such a RAM model, is the timing information in the .db or just an empty box with? When I 'report_lib RAMMDL", the report has one line called "Timing Range: No timing range specified"...Does this indicate the timing information isnt inn the lib? Following is the timing I am interested to see in the .db, which will enable DC t...