@@ -4289,11 +4289,81 @@ unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
42894289/// threads. To achieve this, a fence prevents the compiler and CPU from reordering certain types of
42904290/// memory operations around it.
42914291///
4292- /// A fence 'A' which has (at least) [`Release`] ordering semantics, synchronizes
4293- /// with a fence 'B' with (at least) [`Acquire`] semantics, if and only if there
4294- /// exist operations X and Y, both operating on some atomic object 'm' such
4295- /// that A is sequenced before X, Y is sequenced before B and Y observes
4296- /// the change to m. This provides a happens-before dependence between A and B.
4292+ /// There are 3 different ways to use an atomic fence:
4293+ ///
4294+ /// - atomic - fence synchronization: an atomic operation with (at least) [`Release`] ordering
4295+ /// semantics synchronizes with a fence with (at least) [`Acquire`] ordering semantics.
4296+ /// - fence - atomic synchronization: a fence with (at least) [`Release`] ordering semantics
4297+ /// synchronizes with an atomic operation with (at least) [`Acquire`] ordering semantics.
4298+ /// - fence - fence synchronization: a fence with (at least) [`Release`] ordering semantics
4299+ /// synchronizes with a fence with (at least) [`Acquire`] ordering semantics.
4300+ ///
4301+ /// These 3 ways complement the regular, fence-less, atomic - atomic synchronization.
4302+ ///
4303+ /// ## Atomic - Fence
4304+ ///
4305+ /// An atomic operation on one thread will synchronize with a fence on another thread when:
4306+ ///
4307+ /// - on thread 1:
4308+ /// - an atomic operation 'X' with (at least) [`Release`] ordering semantics on some atomic
4309+ /// object 'm',
4310+ ///
4311+ /// - is paired on thread 2 with:
4312+ /// - an atomic read 'Y' with any order on 'm',
4313+ /// - followed by a fence 'B' with (at least) [`Acquire`] ordering semantics.
4314+ ///
4315+ /// This provides a happens-before dependence between X and B.
4316+ ///
4317+ /// ```text
4318+ /// Thread 1 Thread 2
4319+ ///
4320+ /// m.store(3, Release); X ---------
4321+ /// |
4322+ /// |
4323+ /// -------------> Y if m.load(Relaxed) == 3 {
4324+ /// B fence(Acquire);
4325+ /// ...
4326+ /// }
4327+ /// ```
4328+ ///
4329+ /// ## Fence - Atomic
4330+ ///
4331+ /// A fence on one thread will synchronize with an atomic operation on another thread when:
4332+ ///
4333+ /// - on thread:
4334+ /// - a fence 'A' with (at least) [`Release`] ordering semantics,
4335+ /// - followed by an atomic write 'X' with any ordering on some atomic object 'm',
4336+ ///
4337+ /// - is paired on thread 2 with:
4338+ /// - an atomic operation 'Y' with (at least) [`Acquire`] ordering semantics.
4339+ ///
4340+ /// This provides a happens-before dependence between A and Y.
4341+ ///
4342+ /// ```text
4343+ /// Thread 1 Thread 2
4344+ ///
4345+ /// fence(Release); A
4346+ /// m.store(3, Relaxed); X ---------
4347+ /// |
4348+ /// |
4349+ /// -------------> Y if m.load(Acquire) == 3 {
4350+ /// ...
4351+ /// }
4352+ /// ```
4353+ ///
4354+ /// ## Fence - Fence
4355+ ///
4356+ /// A fence on one thread will synchronize with a fence on another thread when:
4357+ ///
4358+ /// - on thread 1:
4359+ /// - a fence 'A' which has (at least) [`Release`] ordering semantics,
4360+ /// - followed by an atomic write 'X' with any ordering on some atomic object 'm',
4361+ ///
4362+ /// - is paired on thread 2 with:
4363+ /// - an atomic read 'Y' with any ordering on 'm',
4364+ /// - followed by a fence 'B' with (at least) [`Acquire`] ordering semantics.
4365+ ///
4366+ /// This provides a happens-before dependence between A and B.
42974367///
42984368/// ```text
42994369/// Thread 1 Thread 2
@@ -4308,18 +4378,20 @@ unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
43084378/// }
43094379/// ```
43104380///
4311- /// Note that in the example above, it is crucial that the accesses to `m` are atomic. Fences cannot
4312- /// be used to establish synchronization among non-atomic accesses in different threads. However,
4313- /// thanks to the happens-before relationship between A and B, any non-atomic accesses that
4314- /// happen-before A are now also properly synchronized with any non-atomic accesses that
4315- /// happen-after B.
4381+ /// ## Mandatory Atomic
4382+ ///
4383+ /// Note that in the examples above, it is crucial that the access to `m` are atomic. Fences cannot
4384+ /// be used to establish synchronization between non-atomic accesses in different threads. However,
4385+ /// thanks to the happens-before relationship, any non-atomic access that happen-before the atomic
4386+ /// operation or fence with (at least) [`Release`] ordering semantics are now also properly
4387+ /// synchronized with any non-atomic accesses that happen-after the atomic operation or fence with
4388+ /// (at least) [`Acquire`] ordering semantics.
43164389///
4317- /// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize
4318- /// with a fence.
4390+ /// ## Memory Ordering
43194391///
4320- /// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`]
4321- /// and [`Release`] semantics, participates in the global program order of the
4322- /// other [`SeqCst`] operations and/or fences.
4392+ /// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`] and [`Release`]
4393+ /// semantics, participates in the global program order of the other [`SeqCst`] operations and/or
4394+ /// fences.
43234395///
43244396/// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings.
43254397///
0 commit comments