[cpp-threads] [Javamemorymodel-discussion] there's a happens-before orderhere. right?

Alexander Terekhov alexander.terekhov at gmail.com
Mon Dec 15 22:04:19 GMT 2008


On Mon, Dec 15, 2008 at 9:38 PM, Boehm, Hans <hans.boehm at hp.com> wrote:
>
> [I think all of this is relevant to Java only in that vaguely similar
> extensions have been considered there at times.  Most of it
> doesn't currently translate, in spite of the fact that the basic
> memory models are similar.]
>
>> From: Alexander Terekhov [mailto:alexander.terekhov at gmail.com]
>> On Sat, Dec 13, 2008 at 2:04 AM, Boehm, Hans
>> <hans.boehm at hp.com> wrote:
>> [...]
>> >>
>> http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/threadsintro.html#examples
>> >>
>> >> would you label the following C++0x program
>> >>
>> >>     int data; //= 0
>> >>     atomic<int> x; //= 0
>> >>
>> >>     thread 1:
>> >>     ------------
>> >>     data = 1;
>> >>     x.store(1, release);
>> >>
>> >>     thread 2:
>> >>     ------------
>> >>     if (x.load(relaxed))
>> >>       data = 2;
>> >>
>> >> data-race-free or not? Why? TIA.
>> >>
>> > This is well in the "escapes from sequential consistency" category,
>> > and it doesn't currently have a Java analog.
>>
>> Yes. I'm actually driving at
>>
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2745.html
>>
>> > As I said, I was really trying to steer most people well away from
>> > this kind of code.
>>
>> The problem is that std::atomic<> in SC mode is utterly
>> expensive on POWER. Even in acquire-release mode it will
>> inject way too much totally redundant (lw/i)sync(hronization).
>
> I agree that this can be an issue on some current architectures,
> as it is with Java volatiles.  But the above example can be fixed
> by either:
>
> 1) Using an acquire load, or

using an atomic_thread_fence(memory_order_acquire)

[...]

>> > if (r1 = x.load(memory_order_relaxed)) {
>> >    data.store(2, memory_order_relaxed); } else {
>> >    data.store(2, memory_order_relaxed); }
>> >
>> > to be ordered, for example.
>>
>> Why not?
>
> Any compiler that cares about code size is likely to transform this to
>
> r1 = x.load(memory_order_relaxed);
> data.store(2, memory_order_relaxed);
>
> and go from there, rordering at will, and allowing the hardware to reorder.
>
> Preventing this is hard, since the actual code may look like
>
> inside f():
>
>  r1 = x.load(memory_order_relaxed);
>  g(r1);
>
> inside g(), in a separate compilation unit:

You're using the term not defined in the current C++ standard
("compilation unit").

FWIW, it is fine to restrict reordering of

if (r1 = x.load(memory_order_relaxed)) {
   data.store(2, memory_order_relaxed); } else {
   data.store(2, memory_order_relaxed); }

only in the same "scope". ;-)

regards,
alexander.



More information about the cpp-threads mailing list