[cpp-threads] Visibility question

Peter Dimov pdimov at mmltd.net
Wed Aug 2 00:10:50 BST 2006


Boehm, Hans wrote:
> Clark brought up the following interesting question that I couldn't
> immediately answer.  I think I now have the answer, but I thought I
> would post it here to make sure we agree.
>
> The question is whether "raw", i.e. unordered, atomic operations
> should contribute to the happens-before relation.
>
> As a particular example of what I mean, consider (x,y,z atomic, w
> ordinary, everything initially zero):
>
> Thread 1:
> w = 1; // ordinary store
> y.fetch_add<ordered>(1); // ordered atomic; orders
> everything within thread
> x.store<raw>(1);
>
> Thread 2:
> r2 = x.load<raw>();
> z.fetch_add<ordered>(1); // ordered atomic; orders
> everything within thread; different variable
> if (r2) r1 = w; // ordinary load
>
> Is there a data race on w?

I believe that the answer should be "no", in the above and in the following:

T1:
w = 1;
fence();
x.store<raw>(1);

T2:
r2 = x.load<raw>();
fence();
if (r2) r1 = w; // ordinary load

which is, in turn, a different (potentially less efficient) reformulation of

T1:
w = 1;
x.store<release>(1);

T2:
r2 = x.load<acquire>();
if (r2) r1 = w; // ordinary load

and this is plain as day. :-)

> Thinking about this example a bit more. I'm not 100% comfortable with
> either answer.  With the synchronization edge, it's clear that ordered
> atomic updates are not equivalent to the nonatomic version, even if
> they operate on thread-private data.  That's ugly, though probably
> not a showstopper for C++.

Since an <ordered> atomic is a superset of fence(), it seems reasonable (to 
me) for it to not be equivalent to an ordinary op even when operating on 
private data.




More information about the cpp-threads mailing list