# Re: questions about memory_order_seq_cst fence

*From*: Joshua Maurice <joshuamaurice@xxxxxxxxx>*Date*: Tue, 14 Jun 2011 16:44:37 -0700 (PDT)

On Jun 14, 3:05 pm, Anthony Williams <anthony....@xxxxxxxxx> wrote:

Masakuni Oishi <yam...@xxxxxxxxxxxx> writes:

/*** code 1 ***/

// Initially

atomic<int> x(0), y(0);

// Thread 1:

y.store(1, memory_order_release);

atomic_thread_fence(memory_order_seq_cst);

r1 = x.load(memory_order_acquire);

// Thread 2:

x.store(1, memory_order_release);

// Thread 3:

r2 = x.load(memory_order_acquire);

atomic_thread_fence(memory_order_seq_cst);

r3 = y.load(memory_order_acquire);

/***************/

In the above code, is r1 == 0 && r2 == 1 && r3 == 0 possible?

I think it should be prohibited, but I couldn't make sure that

from the C++0x FDIS.

Premise 1: r3 == 0.

Since the only store to y is the store of 1 by thread 1, r3 == 0 implies

that the load from y on thread 3 is reading the initial value of y.

29.3p6 of N3290 says:

"For atomic operations A and B on an atomic object M, where A modifies M

and B takes its value, if there are memory_order_seq_cst fences X and Y

such that A is sequenced before X, Y is sequenced before B, and X

precedes Y in S, then B observes either the eﬀects of A or a later

modification of M in its modification order."

If the fence in thread 1 precedes the fence in thread 3 in S, then the

read at r3 must therefore see the value written by the store in thread

1. Consequently, the fence in thread 3 must precede the fence in thread

1 in S.

Premise 2: r2 == 1.

The load of x in thread 3 reading 1 implies it has read the value of the

store to x from thread 2.

I agree with your proof up to this point.

We already know that the fence in thread 3 precedes the fence in thread

1 in S.

29.3p7 of N3290 says:

"For atomic operations A and B on an atomic object M, if there are

memory_order_seq_cst fences X and Y such that A is sequenced before X, Y

is sequenced before B, and X precedes Y in S, then B occurs later than A

in the modification order of M."

In our case, the fence in thread 3 occurs before the fence in thread 1

in S. The fence in thread 3 is thus X, the fence in thread 1 Y, the read

from x in thread 3 is A and the read from x in thread 1 is B.

Thus the read of x in thread 1 must occur later in the modification

order of x than the read in thread 3. Since the read in thread 3 is of

the last store to x (1), the read in thread 1 must also read that value,

and r1 == 1.

I disagree with this. I think you made the same mistake which I made

in my first post of this thread. Only /modifications/ appear in a

modification order. Reads do not appear in the modification order. At

least, this is the simple reading of 1.10 / 7, and its name is

"modification order", not "access order". Also note that the

definition of a "release sequence" in 1.10 / 8 does not make sense if

reads may appear in modification orders. Also note that the definition

of "visible sequence of side effects" in 1.10 / 14 does not make sense

if reads may appear in modification orders. (Note that there's some

ambiguity w.r.t. volatile atomic objects, as volatile reads do count

as side effects, but non-volatile reads AFAIK are not side effects.)

As I'm beginning to understand this, there is a typo in 29.3 / 7. The

exact text is:

[]

For atomic operations A and B on an atomic object M, if there are

memory_order_seq_cst fences X and Y such that A is sequenced before X,

Y is sequenced before B, and X precedes Y in S, then B occurs later

than A in the modification order of M.

[/]

I think it's meant to read:

[]

For atomic **write (and atomic read-modify-write operations)** A and B

on an atomic object M, if there are memory_order_seq_cst fences X and

Y such that A is sequenced before X, Y is sequenced before B, and X

precedes Y in S, then B occurs later than A in the modification order

of M.

[/]

When you said "the read from x in thread 3 is A and the read from x in

thread 1 is B.", that is where you went wrong. You cannot apply

"29.3 / 7" to atomic reads A and B on an atomic object M, only atomic

writes (and atomic read-modify-write operations).

I'm still dealing with the implication that A precedes B in the total

order S of seq_cst operations does not imply that A happens-before B

nor A inter-thread happens before B nor A synchronizes-with B - and

that's irritating and slightly surprising. At least, I haven't yet

found a rule which states that, and I've looked decently hard, and

I've even found a note saying as much in 29.3 / 8.

I'm still looking at the standard and the code of the OP, if only for

my own sake. I'm leaning towards Masakuni Oishi's interpretation at

the moment. Have I mentioned non-seq_cst code is a bitch to reason

about?

As always, please correct me when I'm wrong.

.

**Follow-Ups**:**Re: questions about memory_order_seq_cst fence***From:*Masakuni Oishi

**Re: questions about memory_order_seq_cst fence***From:*Anthony Williams

**References**:**questions about memory_order_seq_cst fence***From:*Masakuni Oishi

**Re: questions about memory_order_seq_cst fence***From:*Anthony Williams

- Prev by Date:
**Re: questions about memory_order_seq_cst fence** - Next by Date:
**Re: questions about memory_order_seq_cst fence** - Previous by thread:
**Re: questions about memory_order_seq_cst fence** - Next by thread:
**Re: questions about memory_order_seq_cst fence** - Index(es):