[cpp-threads] Yet another visibility question

Boehm, Hans hans.boehm at hp.com
Wed Dec 20 19:06:12 GMT 2006


> From:  Doug Lea
> Sent: Tuesday, December 19, 2006 5:44 PM
> To: C++ threads standardisation
> Subject: Re: [cpp-threads] Yet another visibility question
> 
> Peter Dimov wrote:
> > Boehm, Hans wrote:
> > 
> >> We can argue about whether this should be considered a real 
> >> dependency. But as I argued earlier with Peter, if we assume it 
> >> isn't, I think dependency-based ordering becomes largely 
> useless to 
> >> the programmer, since I can't reason about it without 
> looking through 
> >> abstraction boundaries.
> > 
> > I don't agree. Provable dependencies are not uncommon and 
> in this case 
> > I can use a raw/release atomic. Unprovable dependencies 
> will need an 
> > acquire. I can live with that.
> > 
> 
> Maybe I'm not following this discussion closely enough, but 
> it would seem that if you want to impose an ordering, then 
> you should always state it, and then let the compiler worry 
> about whether that actually requires a fence on the platform 
> you run on?
> 
> In other words, the following would almost never be correct:
>    r1 = x.load_raw(); // should be load_acquire
>    r2 = *r1;
> And maybe tools could help find such errors.
> 
> Or am I missing the point?
> 
> The alternative of defining dependencies seems to me to be a 
> losing battle, at least in C++.
> 
I think we mostly agree on your example.  And I'm increasingly inclined
to agree with your overall conclusion, though I think it's worth
exploring the alternatives in detail, since I'm sure this issue will
continue to get raised.  And the original Java arguments don't apply
completely, since I think it's OK to limit optimization on unordered
atomics much more than we could tolerate for ordinary Java variables.

The question is whether we should enforce dependency-based ordering for
a (possibly unordered atomic) store that depends on an unordered atomic
load.

Pro 1: Otherwise it appears you have to resort to assembly code for
optimal performance for things like reference counting on architectures
like PowerPC.  I would be surprised if the compiler could remove the
extra ordering constraint under realistic conditions.  If you require an
"ordered" constraint on a fetch_add instead of "release", it typically
implicitly orders lots of other non-dependent operations, most of which
are likely to not be in the same compilation unit, and I suspect it's
usually impossible for the compiler to know that none of those matter,
and that hardware-provided dependency-based ordering would be enough.
At least that's my intuition.

Pro 2: In our current formulation, dependency-based ordering is what
prohibits "causal cycles", and hence "out of thin air" results.  But I'm
reasonably optimistic that we could express a similar constraint that
does not actually imply dependency-based ordering.

Pro 3: At a superficial level, it seems weird not to require such
ordering for at least unordered atomic stores, since we are already
prohibiting all kinds of speculative stores.

Con (a showstopper, I think): We don't know how to express
dependency-based ordering in a way that's not broken by conventional
optimizations on other compilation units that don't mention atomics, and
remains usable of the store takes place on the far side of an
abstraction boundary.

Hans



More information about the cpp-threads mailing list