@@ -1550,12 +1550,30 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
1550
1550
1551
1551
/// An atomic fence.
1552
1552
///
1553
- /// A fence 'A' which has [`Release`] ordering semantics, synchronizes with a
1554
- /// fence 'B' with (at least) [`Acquire`] semantics, if and only if there exists
1555
- /// atomic operations X and Y, both operating on some atomic object 'M' such
1553
+ /// Depending on the specified order, a fence prevents the compiler and CPU from
1554
+ /// reordering certain types of memory operations around it.
1555
+ /// That creates synchronizes-with relationships between it and atomic operations
1556
+ /// or fences in other threads.
1557
+ ///
1558
+ /// A fence 'A' which has (at least) [`Release`] ordering semantics, synchronizes
1559
+ /// with a fence 'B' with (at least) [`Acquire`] semantics, if and only if there
1560
+ /// exist operations X and Y, both operating on some atomic object 'M' such
1556
1561
/// that A is sequenced before X, Y is synchronized before B and Y observes
1557
1562
/// the change to M. This provides a happens-before dependence between A and B.
1558
1563
///
1564
+ /// ```text
1565
+ /// Thread 1 Thread 2
1566
+ ///
1567
+ /// fence(Release); A --------------
1568
+ /// x.store(3, Relaxed); X --------- |
1569
+ /// | |
1570
+ /// | |
1571
+ /// -------------> Y if x.load(Relaxed) == 3 {
1572
+ /// |-------> B fence(Acquire);
1573
+ /// ...
1574
+ /// }
1575
+ /// ```
1576
+ ///
1559
1577
/// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize
1560
1578
/// with a fence.
1561
1579
///
@@ -1569,6 +1587,37 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
1569
1587
///
1570
1588
/// Panics if `order` is [`Relaxed`].
1571
1589
///
1590
+ /// # Examples
1591
+ ///
1592
+ /// ```
1593
+ /// use std::sync::atomic::AtomicBool;
1594
+ /// use std::sync::atomic::fence;
1595
+ /// use std::sync::atomic::Ordering;
1596
+ ///
1597
+ /// // A mutual exclusion primitive based on spinlock.
1598
+ /// pub struct Mutex {
1599
+ /// flag: AtomicBool,
1600
+ /// }
1601
+ ///
1602
+ /// impl Mutex {
1603
+ /// pub fn new() -> Mutex {
1604
+ /// Mutex {
1605
+ /// flag: AtomicBool::new(false),
1606
+ /// }
1607
+ /// }
1608
+ ///
1609
+ /// pub fn lock(&self) {
1610
+ /// while !self.flag.compare_and_swap(false, true, Ordering::Relaxed) {}
1611
+ /// // This fence syncronizes-with store in `unlock`.
1612
+ /// fence(Ordering::Acquire);
1613
+ /// }
1614
+ ///
1615
+ /// pub fn unlock(&self) {
1616
+ /// self.flag.store(false, Ordering::Release);
1617
+ /// }
1618
+ /// }
1619
+ /// ```
1620
+ ///
1572
1621
/// [`Ordering`]: enum.Ordering.html
1573
1622
/// [`Acquire`]: enum.Ordering.html#variant.Acquire
1574
1623
/// [`SeqCst`]: enum.Ordering.html#variant.SeqCst
0 commit comments