Skip to content

Commit 15b3414

Browse files
committed
Improve the documentation of atomic::fence
Attempt to "fix" two flaws of the current documentation: 1. The over-emphasis of fence - fence synchronization, relegating atomic - fence and fence - atomic synchronization to second fiddle. 2. The lack of explanation as to how to properly perform atomic - fence and fence - atomic synchronization. It does so by first making it clear that there are 3 different ways to use an atomic fence, then presenting a full example for each usecase, noting the particular position of the fence with regard to the atomic operation, and rounding up with generic notes.
1 parent c6efb90 commit 15b3414

File tree

1 file changed

+87
-15
lines changed

1 file changed

+87
-15
lines changed

library/core/src/sync/atomic.rs

Lines changed: 87 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)