@@ -4277,11 +4277,81 @@ unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
42774277/// threads. To achieve this, a fence prevents the compiler and CPU from reordering certain types of
42784278/// memory operations around it.
42794279///
4280- /// A fence 'A' which has (at least) [`Release`] ordering semantics, synchronizes
4281- /// with a fence 'B' with (at least) [`Acquire`] semantics, if and only if there
4282- /// exist operations X and Y, both operating on some atomic object 'm' such
4283- /// that A is sequenced before X, Y is sequenced before B and Y observes
4284- /// the change to m. This provides a happens-before dependence between A and B.
4280+ /// There are 3 different ways to use an atomic fence:
4281+ ///
4282+ /// - atomic - fence synchronization: an atomic operation with (at least) [`Release`] ordering
4283+ /// semantics synchronizes with a fence with (at least) [`Acquire`] ordering semantics.
4284+ /// - fence - atomic synchronization: a fence with (at least) [`Release`] ordering semantics
4285+ /// synchronizes with an atomic operation with (at least) [`Acquire`] ordering semantics.
4286+ /// - fence - fence synchronization: a fence with (at least) [`Release`] ordering semantics
4287+ /// synchronizes with a fence with (at least) [`Acquire`] ordering semantics.
4288+ ///
4289+ /// These 3 ways complement the regular, fence-less, atomic - atomic synchronization.
4290+ ///
4291+ /// ## Atomic - Fence
4292+ ///
4293+ /// An atomic operation on one thread will synchronize with a fence on another thread when:
4294+ ///
4295+ /// - on thread 1:
4296+ /// - an atomic operation 'X' with (at least) [`Release`] ordering semantics on some atomic
4297+ /// object 'm',
4298+ ///
4299+ /// - is paired on thread 2 with:
4300+ /// - an atomic read 'Y' with any order on 'm',
4301+ /// - followed by a fence 'B' with (at least) [`Acquire`] ordering semantics.
4302+ ///
4303+ /// This provides a happens-before dependence between X and B.
4304+ ///
4305+ /// ```text
4306+ /// Thread 1 Thread 2
4307+ ///
4308+ /// m.store(3, Release); X ---------
4309+ /// |
4310+ /// |
4311+ /// -------------> Y if m.load(Relaxed) == 3 {
4312+ /// B fence(Acquire);
4313+ /// ...
4314+ /// }
4315+ /// ```
4316+ ///
4317+ /// ## Fence - Atomic
4318+ ///
4319+ /// A fence on one thread will synchronize with an atomic operation on another thread when:
4320+ ///
4321+ /// - on thread:
4322+ /// - a fence 'A' with (at least) [`Release`] ordering semantics,
4323+ /// - followed by an atomic write 'X' with any ordering on some atomic object 'm',
4324+ ///
4325+ /// - is paired on thread 2 with:
4326+ /// - an atomic operation 'Y' with (at least) [`Acquire`] ordering semantics.
4327+ ///
4328+ /// This provides a happens-before dependence between A and Y.
4329+ ///
4330+ /// ```text
4331+ /// Thread 1 Thread 2
4332+ ///
4333+ /// fence(Release); A
4334+ /// m.store(3, Relaxed); X ---------
4335+ /// |
4336+ /// |
4337+ /// -------------> Y if m.load(Acquire) == 3 {
4338+ /// ...
4339+ /// }
4340+ /// ```
4341+ ///
4342+ /// ## Fence - Fence
4343+ ///
4344+ /// A fence on one thread will synchronize with a fence on another thread when:
4345+ ///
4346+ /// - on thread 1:
4347+ /// - a fence 'A' which has (at least) [`Release`] ordering semantics,
4348+ /// - followed by an atomic write 'X' with any ordering on some atomic object 'm',
4349+ ///
4350+ /// - is paired on thread 2 with:
4351+ /// - an atomic read 'Y' with any ordering on 'm',
4352+ /// - followed by a fence 'B' with (at least) [`Acquire`] ordering semantics.
4353+ ///
4354+ /// This provides a happens-before dependence between A and B.
42854355///
42864356/// ```text
42874357/// Thread 1 Thread 2
@@ -4296,18 +4366,20 @@ unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
42964366/// }
42974367/// ```
42984368///
4299- /// Note that in the example above, it is crucial that the accesses to `m` are atomic. Fences cannot
4300- /// be used to establish synchronization among non-atomic accesses in different threads. However,
4301- /// thanks to the happens-before relationship between A and B, any non-atomic accesses that
4302- /// happen-before A are now also properly synchronized with any non-atomic accesses that
4303- /// happen-after B.
4369+ /// ## Mandatory Atomic
4370+ ///
4371+ /// Note that in the examples above, it is crucial that the access to `m` are atomic. Fences cannot
4372+ /// be used to establish synchronization between non-atomic accesses in different threads. However,
4373+ /// thanks to the happens-before relationship, any non-atomic access that happen-before the atomic
4374+ /// operation or fence with (at least) [`Release`] ordering semantics are now also properly
4375+ /// synchronized with any non-atomic accesses that happen-after the atomic operation or fence with
4376+ /// (at least) [`Acquire`] ordering semantics.
43044377///
4305- /// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize
4306- /// with a fence.
4378+ /// ## Memory Ordering
43074379///
4308- /// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`]
4309- /// and [`Release`] semantics, participates in the global program order of the
4310- /// other [`SeqCst`] operations and/or fences.
4380+ /// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`] and [`Release`]
4381+ /// semantics, participates in the global program order of the other [`SeqCst`] operations and/or
4382+ /// fences.
43114383///
43124384/// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings.
43134385///
0 commit comments