Date: Fri, 9 Oct 2026 15:55:52 +0800
So, what behavior of the program do you think? If you think the program
should be undefined behavior because the program contains a data race,
let's step-by-step to go through the rules in [intro.race] p17. It's true
that `#1` and `#2` are two potentially concurrent conflicting actions, and
neither happens before the other. The crux is whether they satisfy the
condition: at least one of which is not atomic. If one of them is
non-atomic, then the condition is satisfied; therefore, the program
contains a data race. If they are both atomic operations, the condition is
false; no data race is contained. As I commented above, since the standard
lets implementations define the semantics of the access, and a hypothetical
implementation can define `#1` as `std::atomic_ref<int>(value).load()` and
`#2` as `std::atomic_ref<int>(value).store(1)`; i.e., they're atomic
operations, I don't think the crux condition in [intro.race] p17 is true.
So, the program under this specified semantics shouldn't be UB. How do you
explain this point?
On Fri, Oct 9, 2026 at 3:39 PM David Brown <david.brown_at_[hidden]> wrote:
>
>
> On 09/10/2026 09:16, jim x via Std-Discussion wrote:
> > If the implementation defines that accesses to volatile variables
> > are atomic, then they are atomic.
> >
> >
> > In this case, does the program contain a data race as per [intro.race]
> > p17? If not, since the behavior depends on how the implementation define
> > the semantics, does that mean the behavior of the program should be
> > implementation-defined?
> >
>
> "Implementation-defined" in the standards does not just mean that the
> implementation has to treat the construct in some particular way. It
> means that the standard gives a range of options of how the
> implementation should handle the construct, and that the implementation
> must document how it handles them.
>
> If an implementation's manual says that volatile accesses are atomic
> (not unreasonable on single-core non-superscaler targets like most
> microcontrollers), then the programmer can rely on the volatile accesses
> being atomic. But that does not mean unsynchronised volatile accesses
> to the same address in different threads is implementation-defined
> behaviour, or should be called such in the C++ standards.
>
>
>
should be undefined behavior because the program contains a data race,
let's step-by-step to go through the rules in [intro.race] p17. It's true
that `#1` and `#2` are two potentially concurrent conflicting actions, and
neither happens before the other. The crux is whether they satisfy the
condition: at least one of which is not atomic. If one of them is
non-atomic, then the condition is satisfied; therefore, the program
contains a data race. If they are both atomic operations, the condition is
false; no data race is contained. As I commented above, since the standard
lets implementations define the semantics of the access, and a hypothetical
implementation can define `#1` as `std::atomic_ref<int>(value).load()` and
`#2` as `std::atomic_ref<int>(value).store(1)`; i.e., they're atomic
operations, I don't think the crux condition in [intro.race] p17 is true.
So, the program under this specified semantics shouldn't be UB. How do you
explain this point?
On Fri, Oct 9, 2026 at 3:39 PM David Brown <david.brown_at_[hidden]> wrote:
>
>
> On 09/10/2026 09:16, jim x via Std-Discussion wrote:
> > If the implementation defines that accesses to volatile variables
> > are atomic, then they are atomic.
> >
> >
> > In this case, does the program contain a data race as per [intro.race]
> > p17? If not, since the behavior depends on how the implementation define
> > the semantics, does that mean the behavior of the program should be
> > implementation-defined?
> >
>
> "Implementation-defined" in the standards does not just mean that the
> implementation has to treat the construct in some particular way. It
> means that the standard gives a range of options of how the
> implementation should handle the construct, and that the implementation
> must document how it handles them.
>
> If an implementation's manual says that volatile accesses are atomic
> (not unreasonable on single-core non-superscaler targets like most
> microcontrollers), then the programmer can rely on the volatile accesses
> being atomic. But that does not mean unsynchronised volatile accesses
> to the same address in different threads is implementation-defined
> behaviour, or should be called such in the C++ standards.
>
>
>
Received on 2026-10-09 07:56:10
