[cpp-threads] modes

Doug Lea dl at cs.oswego.edu
Sat May 7 16:22:46 BST 2005


This is a picking-up of sorts from my lack of reply to Peter Dimov
last week.

First a reminder of the original intent here, that was never spelled
out very well in our drafts.

My (and I think others) thoughts were were to define a few memory
modes, and then require that things like the to-be-standard lock/unlock
conform to them. (Maybe better would be some kinds of qualifiers for
functions, so you could do this for arbitrary user functions
too, but I don't know how to do that.) Actions on volatiles (now
"mutable volatiles") would also be defined in terms of them, and the
atomic classes would allow more fine-grained control over them.

The more modes you define, the harder this all gets, at least
if you are aiming to specify them all correctly, build
conformance tests, and/or enable the model to be formalized.
So you'd really really like to keep the set small.
But as Peter and Alexander have pointed out, there are more
than a few conceivably-useful modes that we (at least I)
didn't originally have in mind.

However, I think the best tactic here is stubborn resistance!

So I still think we should agree on a very small minimal set, and add
others only if there are compelling use cases for modes needed in
constructions that:
    1. arise in common or important situations,
    2. can't be expressed without special modes,
    3. will remain inefficient even when compilers start
       routinely optimizing wrt memory barriers etc in compliant code,
    4. will remain useful even as hardware vendors continue
       with their (very) recent trends to make most barriers etc cheaper
       (and thus less worthwhile to evade in corner cases).

The minimal list seems to be along the lines of
   read-with-acquire
   write-with-release
   write-preserving-order
   CAS-with-acquire-release
   CAS-with-release
(plus the default ordinary-read and ordinary-write)

We'd still need to spell out the details of exactly what acquire,
release, and write-ordering mean, especially wrt the highly
inconvenient sequence-point wording of the rest of the C++ spec.

Maybe others can try to motivate the next-most-important mode
to see if we think it is worth adding?

A couple of further notes and digressions:

1. In Java atomics, compareAndSet has acquire-release,
and "weakCompareAndSet" has only release, but is also weak in
another sense -- of being allowed to spuriously fail, which
makes it cheaper if mapped to LL/SC. This boils down to pooling two
different semantics. If you want one you live with the other,
which is one reasonable way to keep modes small, and there didn't
seem to be any known usages where this would be a hardship on users.

2. There's very little motivation to define CAS-with-acquire only.
I believe that even Itanium cmpxchg.acq actually has both acq and rel
semantics. So even hardware folks apparently don't think the case is
worth optimizing. And combining acq/rel makes correct usage easier.
Also, as always, I just don't think that explicit LL/SC is worth
exposing. LL/SC instructions tend to have so many restrictions and
quirks that the just about only thing it is good for is CAS/weakCAS
emulation

3. If the list stays about this small, mode-qualifiers
are probably overkill. We might as well just have each correspond
to a method in the atomics classes.

-Doug












More information about the cpp-threads mailing list