Memory model

Herb Sutter hsutter at microsoft.com
Fri Jan 28 20:01:54 GMT 2005


Thanks, Hans. Personally, I feel the same tension I think you do between
#1 and #2.

As for the committee, this is a perfect example of something that
belongs in a classic initial proposal paper that should be brought to a
meeting to be presented to the evolution working group so as to get
their explicit guidance as to their preference on major design
alternatives, in the context of a reasonably complete proposal that has
enough details to help the reader evaluate the tradeoffs of the
alternatives.

When you present it, answers you could get from the committee range
from:

  - "well, we're not interested in this work after all" (unlikely)

  - a clear preference for option 1 or 2

  - a clear preference for some other option, or combination of options

  - division in the EWG where some prefer one and some prefer another
and there's no real consensus (always possible, but this usually changes
later when there are more concrete proposals)

Regardless of the feedback at the first meeting, any such result could
change in the future, but it would still give valuable information about
the group's feelings and their specific concerns which would come up in
discussion.

So this would fit perfectly as part of a paper for Lillehammer. What
would be ideal is a paper with a proposal covering some or all of your
work, that incorporates designed alternatives (with pro/con discussion)
for both paths of major questions. But having this in the context of a
fairly complete proposal would make the discussion more concrete and
useful.

I would also repeat that there are two or three major levels in your
proposal that might work best as separate related proposal papers (this
is probably preferable, esp. as you seem to have different sets of
authors for the different parts), or at least as clearly demarcated
major sections in a single proposal paper. The above question would work
beautifully in the lowest-level proposal paper/section on memory model
and language semantics.

Then, once you have feedback from the EWG, you'd expect to go back and
produce a new version of the paper that addresses/incorporates the
feedback, and adds more detail, and then bring that to the next meeting
and repeat. This part usually takes 1-3 meetings/iterations. Once you
have a version of the proposal that gets clear positive feedback from
EWG without significant design controversies, it's time to come up with
a version that adds the all-important Proposed Wording section that
crafts the standardese. This part usually takes 1-2 meetings.

I've seen the whole process, from initial proposal to adopting wording
into the standards, happen in as few as 2 meetings, though. Walter Brown
got agreement on the hefty mathematical extensions in the Library TR
that quickly. On the other hand, I've also (rarely) seen people bring
proposals for several meetings and get tentative positive feedback, only
to have the committee later decide they just couldn't agree on a version
they could agree to adopt, and the work fell by the wayside (Greg
Colvin's smart pointers went this route in the first standard). Just
trying to set some expectations to strongly encourage you while giving a
realistic view of the effort and timeframe and lack of guarantees in
this process, as well as its great potential success.

How does that sound?

Herb


> -----Original Message-----
> From: Boehm, Hans [mailto:hans.boehm at hp.com]
> Sent: Friday, January 28, 2005 11:39 AM
> To: Herb Sutter
> Cc: ben at decadentplace.org.uk; kevlin at curbralan.com;
> andrei at metalanguage.com; magedm at us.ibm.com; pugh at cs.umd.edu;
> rcbilson at uwaterloo.ca; dl at cs.oswego.edu; Peter A. Buhr; Boehm, Hans
> Subject: RE: Memory model
> 
> Herb -
> 
> We started thinking in a bit more detail about what a C++
> memory model would look like.  I believe we need to make
> a fairly fundamental decision at the outset, which depends
> on other goals of the C++ committee.  We were hoping you might
> be able to provide some guidance.  If Microsoft has a position
> on this, it would also be good to understand that.
> 
> The basic options are:
> 
> 1) We basically stick with the current pthreads approach of
> leaving the behavior of races involving ordinary assignments
> undefined.  (I believe this is also the compiler-writers view
> of the world with win32 threads, outside of .NET,
> though I haven't found documentation there.)  We would have
> to do some work to pin down what this means.  And doing so
> would impose some compiler constraints, e.g. no speculative
> register promotion, and severe restrictions on overwriting
> adjacent struct and class fields.  But it would minimize such
> impact.
> 
> We would view atomic operations, and possibly volatile operations,
> as synchronization actions.  Thus atomic operations (and possibly
> volatile operation) not only could not result in a race, but
> could also help to eliminate races between ordinary variables.
> You could make double-checked locking
> work in this model, but you would need at least a volatile
> declaration.
> 
> This model is different from the Java model, and I think, the
> intent of the .NET model.  It is incompatible with running untrusted
> code in a secure application, since there is nothing to prevent
> untrusted code from introducing a race, and hence invoking undefined
> behavior.  But it seems to be much more in the spirit of current
> standards, which already invoke undefined behavior in many places.
> 
> As a practical matter, it also means, for example, that if p
> is a pointer to a vector of immutable size, then something
> like
> 
> 	my_p = p;
> 	if (i > 0 && i < my_p -> size()) x = p[i];
> 
> is allowed to still generate a subscript error (or do anything
> else), if the pointer p can change concurrently, since the compiler
may,
> for example, reload my_p from p at any time, if it deems
> that to be convenient.
> 
> 2) We go with something much closer to the Java model, in
> which races between ordinary variable accesses have semantics,
> and the model tells you which of the possible memory writes
> may be seen by a read.  I think this is a far more drastic and
> pervasive change for compiler writers.  It would mean that the
> compiler cannot introduce additional reads from globals, e.g.
> to reload a spilled register.
> 
> I think that for this to be meaningful, we also need some
> atomicity guarantees for ordinary variable accesses, especially
> for pointers.  I'm concerned that C++ supports some embedded
> architectures that can't efficiently support atomic pointer loads
> and stores.  X86 implementations with unaligned pointers
> probably wouldn't work anymore, but hopefully nobody does
> that anyway.
> 
> For Java, this was much less of a change, since even the original
> model required it.  And with potentially untrusted code in secure
> applications, I think this is the only viable path.
> 
> ----------------------------
> 
> Based on a prior conversation, at least Doug and I grudgingly
> favor option 1.  It's probably not the route we would go if we were
> designing a language from scratch.  But I don't think we can justify
> the cost of option 2 unless the C++ committee as a whole wants to
> move the language in that direction.  Unfortunately, I think
> this affects many other design decisions.  Thus it would be nice
> to, at least tentatively, resolve this soon.
> 
> Hans






More information about the cpp-threads mailing list