pub(crate) fn fence(order: Ordering)
Expand description
An atomic fence.
Depending on the specified order, a fence prevents the compiler and CPU from reordering certain types of memory operations around it. That creates synchronizes-with relationships between it and atomic operations or fences in other threads.
A fence ‘A’ which has (at least) Release
ordering semantics, synchronizes
with a fence ‘B’ with (at least) Acquire
semantics, if and only if there
exist operations X and Y, both operating on some atomic object ‘M’ such
that A is sequenced before X, Y is sequenced before B and Y observes
the change to M. This provides a happens-before dependence between A and B.
Thread 1 Thread 2
fence(Release); A --------------
x.store(3, Relaxed); X --------- |
| |
| |
-------------> Y if x.load(Relaxed) == 3 {
|-------> B fence(Acquire);
...
}
Atomic operations with Release
or Acquire
semantics can also synchronize
with a fence.
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);
}
}