C++ Logo

std-discussion

Advanced search

Re: Does the C++ abstract machine recognize a temporal order of execution?

From: Jennifier Burnett <jenni_at_[hidden]>
Date: Fri, 12 Jun 2026 08:56:53 +0100
> There is no requirement that an acquire barrier be preceded by a release barrier. All an acquire barrier means is "ensure that no read operation after this instruction can be reordered before this instruction". Similarly, a release barrier means "ensure that all pending write operations are completed before passing beyond this instruction".

This is a common simplification of the memory model but it is incorrect. The standard does not describe things in those terms, it's only concerned with happens-before relationships. The effect of an acquire operation is that if it observes a value from a release sequence headed by a particular release operation then the acquire happens-before the release operation, which through the transitive clause in the definition of happens-before means that all operations preceding the release happen-before all operations succeeding the acquire.

You are maybe correct in an _extremely_ pedantic sense that there's no _explicit_ requirement that an acquire correspond to a release - it just happens to be the case that if you follow the definitions in the standard then an acquire that never observes a value written by a release sequence does not have any semantics different than a relaxed operation.

On 12 June 2026 00:34:14 BST, Simon Cooke <sicooke_at_[hidden]> wrote:
>There is no requirement that an acquire barrier be preceded by a release
>barrier. All an acquire barrier means is "ensure that no read operation
>after this instruction can be reordered before this instruction".
>Similarly, a release barrier means "ensure that all pending write
>operations are completed before passing beyond this instruction".
>
>It's much clearer if you break it out into explicit memory barrier/fence
>instructions. One thing that's misleading is that the acquire/release
>naming makes people think "I'm acquiring some data / I'm releasing some
>data" - which isn't the case. It's named after mutex/critical section
>behavior - acquiring the lock vs. releasing the lock.
>
>Acquiring a lock doesn't require you to release a lock before you do it for
>the first time.
>
>On Wed, Jun 10, 2026 at 10:37 PM Jennifier Burnett <jenni_at_[hidden]>
>wrote:
>
>> An acquire barrier is meaningless in this context. An acquire barrier
>> needs either a release operation or atomic operation preceded by a release
>> barrier to have any semantics beyond relaxed. What exactly would you be
>> establishing a happens-before relationship with in the original example?
>> Assuming the call to now() is an implicit acquire barrier changes nothing
>> about the semantics because there's no corresponding release for it to
>> establish a happens-before relationship with. The first thread doesn't even
>> have any operations other than the call to now() that the acquire barrier
>> would apply to
>>
>> On 11 June 2026 01:37:42 BST, Thiago Macieira via Std-Discussion <
>> std-discussion_at_[hidden]> wrote:
>> >On Wednesday, 10 June 2026 16:24:30 Pacific Daylight Time Simon Cooke
>> wrote:
>> >> If you don't want that, you need acquire semantics, which will prevent
>> the
>> >> write from down after the timestamp() call in #2
>> >
>> >This is the essence of the argument: reading from the monotonic clock
>> should
>> >be an acquire barrier. The Standard does not say it is, but I think it
>> should.
>> >
>>

Received on 2026-06-12 08:08:02