Skip to content

Commit 5431c6f

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 66bc5a4 commit 5431c6f

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
@@ -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

Comments
 (0)