 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
andrew_nuss@yahoo.com Guest
|
Posted: Thu May 17, 2007 1:14 pm Post subject: how to prevent unwanted hoist |
|
|
Hi,
Lets say that I have an AtomicCounter whose declaration is:
class AtomicCounter {
volatile long val;
public:
AtomicCounter();
~AtomicCounter();
long ValueOf () { return val; }
void Increment () { InterlockedIncrement(&val); }
};
And I use it in a function in one thread. In this thread, I only use
the ValueOf() member which I'm quite afraid the compiler might think
is immutable, and hence only check the value once.
class MyStream {
AtomicCounter* counter; // set in constructor
char* buf; // alloced in constructor
int buflen;
int bufpos;
long lastcount;
... // other members
void FillBuf ()
{
... refill buffer
lastcount = counter->Value();
}
public:
char NextChar ()
{
bool dirty = false;
do {
if (dirty || bufpos == buflen)
FillWindow();
char ch = buf[bufpos++];
if (counter->ValueOf() == lastcount)
return ch;
cursor == bufpos--;
dirty = true;
} while (true);
}
};
The point is that ValueOf() might be hoisted by an overly smart
compiler because it appears that counter->Increment() is never called
in the NextChar() function nor the FillWindow() function and so the
compiler thinks it only has to fetch ValueOf() once. Nevertheless,
another thread shares the same counter pointer, and could call counter-
| Quote: | Increment() at any time.
|
I'm wondering if the fact that ValueOf() is not a const function and
the AtomicCounter data member is volatile helps any. Otherwise, what
do I do?
By the way, I think my AtomicCounter works fine on Windows, because
InterlockedIncrement() guarantees that another CPU instantly "sees"
the updated "val" member. On Unix, I have further trouble. I think
that Increment() and ValueOf() both need to use a mutex to ensure that
changes to "val" are seen instantly by the other CPU thread. Then
ValueOf() becomes way to slow for the performance of NextChar(). I
wish ValueOf() didn't need to use the mutex.
Thanks,
Andy
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Pedro Lamarão Guest
|
Posted: Thu May 17, 2007 11:15 pm Post subject: Re: how to prevent unwanted hoist |
|
|
On May 17, 10:14 am, "andrew_n...@yahoo.com" <andrew_n...@yahoo.com>
wrote:
| Quote: | The point is that ValueOf() might be hoisted by an overly smart
compiler because it appears that counter->Increment() is never called
in the NextChar() function nor the FillWindow() function and so the
compiler thinks it only has to fetch ValueOf() once. Nevertheless,
another thread shares the same counter pointer, and could call counter-
Increment() at any time.
I'm wondering if the fact that ValueOf() is not a const function and
the AtomicCounter data member is volatile helps any. Otherwise, what
do I do?
|
Since the compiler is forbidden to assume anything about the current
value of a volatile object, it can never assume anything about the
result of calling ValueOf. I don't think any compiler will "cache"
this result. I think you are safe.
--
Pedro Lamarão
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Denise Kleingeist Guest
|
Posted: Sun May 20, 2007 6:57 am Post subject: Re: how to prevent unwanted hoist |
|
|
Hello Andrew!
On May 17, 3:14 pm, "andrew_n...@yahoo.com" <andrew_n...@yahoo.com>
wrote:
| Quote: | class AtomicCounter {
volatile long val;
|
The next revision of the C++ standard will provide support for
atomic operations. The exact details are still under discussion
and currently I can't come up with the exact notation how this
would look like.
In any case, declaring your variable to be volatile won't have
much of an effect with respect to multiple threads accessing it
simultanously. Neither current nor future compilers will honour
it in a form useful for multi-threading purposes. However, it
should already prevent the compiler from hoisting access to it
from the loop but since it doesn't introduce any kind for memory
fences, that's about it.
Good luck, Denise
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Le Chaud Lapin Guest
|
Posted: Sun May 20, 2007 11:48 pm Post subject: Re: how to prevent unwanted hoist |
|
|
On May 20, 1:57 am, Denise Kleingeist
<denise.kleinge...@googlemail.com> wrote:
| Quote: | Hello Andrew!
On May 17, 3:14 pm, "andrew_n...@yahoo.com" <andrew_n...@yahoo.com
wrote:
class AtomicCounter {
volatile long val;
The next revision of the C++ standard will provide support for
atomic operations. The exact details are still under discussion
and currently I can't come up with the exact notation how this
would look like.
In any case, declaring your variable to be volatile won't have
much of an effect with respect to multiple threads accessing it
simultanously. Neither current nor future compilers will honour
it in a form useful for multi-threading purposes. However, it
should already prevent the compiler from hoisting access to it
from the loop but since it doesn't introduce any kind for memory
fences, that's about it.
|
This is a good point.
It is not clear to me what the OP's algorithm is, but the presence of
an unbalanced synchronization primitive is highly suspect.
InterlockedIncrement only guarantees atomicity with respect to other
Interlocked* functions. A naked increment will ruin the point of
using Interlocked* in the first place. This principle is not specific
to Windows.
In other words, there is a model/mood for doing synchronization that
the compiler cannot provide, and must be conscientiously engineered by
the programmer, then, after that, the elements of synchronization in
the language and the library can be brought to bear upon the design.
-Le Chaud Lapin-
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|