[cpp-threads] Web site updated
Peter Dimov
pdimov at mmltd.net
Tue Feb 13 22:21:29 GMT 2007
Boehm, Hans wrote:
> But I think that combining accesses can also be a problem at user
> level, for other reasons. If I write
>
> Thread1:
> for(;;) {
> a.store_relaxed(0); // or release
> a.store_relaxed(1);
> }
>
> Thread2:
> while (a.load_relaxed());
> <do something useful>
>
> Should I expect thread 2 to eventually make progress? Clearly if the
> first a.store_relaxed() is elided, the answer is no. But an answer of
> "yes" is probably more desirable.
This is an interesting example since thread 1 can be equivalently
transformed to
a.store_relaxed(0);
for(;;) {
a.store_relaxed(1); // or release
a.store_relaxed(0);
}
where combining the stores will give a different result. But does it
correspond to a sensible real-world case?
Either way, my point is that we already have a "dumb mode" switch, it's
called volatile. If a is marked volatile:
volatile int a;
for( ;; )
{
atomic_store_relaxed( &a, 0 );
atomic_store_relaxed( &a, 1 );
}
this gives the programmer the intended effects of a thread toggling a
between 0 and 1. So this is one way to keep volatile and atomic separate and
orthogonal. We already decided to not make volatile imply atomic, so it only
makes sense to consistently apply this principle in the other direction and
state that atomic does not necessarily imply volatile.
Or not. But I can see many optimization opportunities being lost. It would
be rare for two relaxed accesses to appear next to one another in the source
code, but inlining several functions and then reordering the basic block
will routinely produce such examples. In fact, _release and _acquire will
suffer even more because of the redundant barriers.
More information about the cpp-threads
mailing list