[Voted into WP at March, 2010 meeting.]
Proposed resolution (October, 2009): Change 6.10.2 [intro.multithread] paragraph 12 as follows:
...The value of a non-atomic scalar object or bit-field M, as
determined by evaluation B, shall be the value stored by the
visible side effect A. [Note: If there is ambiguity
about which side effect to a non-atomic object or bit-field is
visible, then
there is a data race, and the behavior is
either unspecified or undefined. —end note]...
6.10.2 [intro.multithread] paragraph 12 says, A visible side effect A on an object M with
respect to a value computation B of M satisfies the
conditions:
A happens before B, and there is no other side effect X to M such that
A happens before X and X happens before
B. The value of a non-atomic scalar object M, as determined by
evaluation B, shall be the value stored by the visible side
effect A. [Note: If there is ambiguity about which side
effect to a non-atomic object is visible, then there is a data race,
and the behavior is undefined. —end note] The note here suggests that, except in the case of a data race,
visible side effects to value computation can always be determined.
But unsequenced and indeterminately sequenced side effects on the same
object create ambiguities with respect to a later value computation as
well. So the wording needs to be revisited, see the following
examples. According to the definition in the draft, both A and B are visible
side effects to C. However, there is no data race, because (paragraph
14) a race involves at least two threads. So the note in paragraph 12
is logically false. The model introduces the special case of indeterminately sequenced
side effects, that leave open what execution order is taken in a
concrete situation. If the execution paths access the same data,
unpredictable results are possible, just as it is the case with data
races. Whereas data races constitute undefined behavior,
indeterminatedly sequenced side effects on the same object do not. As
a consequence of this disparity, indeterminately sequenced execution
occasionally needs exceptional treatment. Here, either A or B is the visible side effect on the value
computation C, but you cannot tell which (cf. 6.10.1 [intro.execution] paragraph 16)
. Although an ambiguity is present, it is neither
because of a data race, nor is the behavior undefined, in total
contradiction to the note.
int main(){
int i = 0;
i = // unsequenced side effect A
i++; // unsequenced side effect B
return i; // value computation C
}
int i = 0;
int f(){
return
i = 1; // side effect A
}
int g(){
return
i = 2; // side effect B
}
int h(int, int){
return i; // value computation C
}
int main(){
return h(f(),g()); // function call D returns 1 or 2?
}