fence in std::sync::atomic - Rust
Description: An atomic fence.

## fence

# Function fence

1.0.0 · Source

    pub fn fence(order: Ordering)

Expand description

An atomic fence.

Fences create synchronization between themselves and atomic operations or fences in other threads. To achieve this, a fence prevents the compiler and CPU from reordering certain types of memory operations around it.

There are 3 different ways to use an atomic fence:

- atomic - fence synchronization: an atomic operation with (at least) `Release` ordering semantics synchronizes with a fence with (at least) `Acquire` ordering semantics.
- fence - atomic synchronization: a fence with (at least) `Release` ordering semantics synchronizes with an atomic operation with (at least) `Acquire` ordering semantics.
- fence - fence synchronization: a fence with (at least) `Release` ordering semantics synchronizes with a fence with (at least) `Acquire` ordering semantics.

These 3 ways complement the regular, fence-less, atomic - atomic synchronization.

### §Atomic - Fence

An atomic operation on one thread will synchronize with a fence on another thread when:

- on thread 1:

  - an atomic operation ‘X’ with (at least) `Release` ordering semantics on some atomic object ‘m’,

- is paired on thread 2 with:

  - an atomic read ‘Y’ with any order on ‘m’,
  - followed by a fence ‘B’ with (at least) `Acquire` ordering semantics.

This provides a happens-before dependence between X and B.

        Thread 1                                          Thread 2

    m.store(3, Release); X ---------
                                   |
                                   |
                                   -------------> Y  if m.load(Relaxed) == 3 {
                                                  B      fence(Acquire);
                                                         ...
                                                     }

### §Fence - Atomic

A fence on one thread will synchronize with an atomic operation on another thread when:

- on thread:

  - a fence ‘A’ with (at least) `Release` ordering semantics,
  - followed by an atomic write ‘X’ with any ordering on some atomic object ‘m’,

- is paired on thread 2 with:

  - an atomic operation ‘Y’ with (at least) `Acquire` ordering semantics.

This provides a happens-before dependence between A and Y.

        Thread 1                                          Thread 2

    fence(Release);      A
    m.store(3, Relaxed); X ---------
                                   |
                                   |
                                   -------------> Y  if m.load(Acquire) == 3 {
                                                         ...
                                                     }

### §Fence - Fence

A fence on one thread will synchronize with a fence on another thread when:

- on thread 1:

  - a fence ‘A’ which has (at least) `Release` ordering semantics,
  - followed by an atomic write ‘X’ with any ordering on some atomic object ‘m’,

- is paired on thread 2 with:

  - an atomic read ‘Y’ with any ordering on ‘m’,
  - followed by a fence ‘B’ with (at least) `Acquire` ordering semantics.

This provides a happens-before dependence between A and B.

        Thread 1                                          Thread 2

    fence(Release);      A --------------
    m.store(3, Relaxed); X ---------    |
                                   |    |
                                   |    |
                                   -------------> Y  if m.load(Relaxed) == 3 {
                                        |-------> B      fence(Acquire);
                                                         ...
                                                     }

### §Mandatory Atomic

Note that in the examples above, it is crucial that the access to `m` are atomic. Fences cannot be used to establish synchronization between non-atomic accesses in different threads. However, thanks to the happens-before relationship, any non-atomic access that happen-before the atomic operation or fence with (at least) `Release` ordering semantics are now also properly synchronized with any non-atomic accesses that happen-after the atomic operation or fence with (at least) `Acquire` ordering semantics.

### §Memory Ordering

A fence which has `SeqCst` ordering, in addition to having both `Acquire` and `Release` semantics, participates in the global program order of the other `SeqCst` operations and/or fences.

Accepts `Acquire`, `Release`, `AcqRel` and `SeqCst` orderings.

## §Panics

Panics if `order` is `Relaxed`.

## §Examples

    use std::sync::atomic::AtomicBool;
    use std::sync::atomic::fence;
    use std::sync::atomic::Ordering;

    // A mutual exclusion primitive based on spinlock.
    pub struct Mutex {
        flag: AtomicBool,
    }

    impl Mutex {
        pub fn new() -> Mutex {
            Mutex {
                flag: AtomicBool::new(false),
            }
        }

        pub fn lock(&self) {
            // Wait until the old value is `false`.
            while self
                .flag
                .compare_exchange_weak(false, true, Ordering::Relaxed, Ordering::Relaxed)
                .is_err()
            {}
            // This fence synchronizes-with store in `unlock`.
            fence(Ordering::Acquire);
        }

        pub fn unlock(&self) {
            self.flag.store(false, Ordering::Release);
        }
    }