Atomics
API summary (generated from the Beans source by npm run coverage): 2 types · 1 static method · 13 instance methods · 5 enum variants.
Atomic<T> is a single cell that many threads can read and change safely, without
a lock. Each change is one indivisible step. This page lists every operation, the
five memory orders, and the wait/notify calls. For threads in general, see
concurrency.
What Atomic holds
Section titled “What Atomic holds”An Atomic<T> holds exactly one integer or one bool. It cannot hold a decimal
or a float.
let counter: Atomic<i64> = new Atomic<i64>(0)A narrow cell wraps within its width. Atomic<bool> is a one-byte cell holding 0
or 1.
Operations
Section titled “Operations”Every read-modify-write operation returns the value it replaced (the old value).
Atomic<T>.load(MemoryOrder) -> TAtomic<T>.store(T, MemoryOrder)Atomic<T>.exchange(T, MemoryOrder) -> TAtomic<T>.fetch_add(T, MemoryOrder) -> TAtomic<T>.fetch_sub(T, MemoryOrder) -> TAtomic<T>.fetch_and(T, MemoryOrder) -> TAtomic<T>.fetch_or(T, MemoryOrder) -> TAtomic<T>.fetch_xor(T, MemoryOrder) -> TAtomic<T>.compare_exchange(T, T, MemoryOrder, MemoryOrder) -> boolload(order)reads the value;store(v, order)writesv.exchange(v, order)setsvand returns the old value.fetch_add(v, order)andfetch_sub(v, order)add or subtract and return the old value. Both need an integer cell.fetch_and,fetch_or, andfetch_xordo a bitwise operation and return the old value.compare_exchange(expected, desired, success_order, failure_order)compares the cell withexpected; if they match it setsdesiredand returnstrue, otherwise it leaves the cell alone and returnsfalse. It takes two orders: one for the path that wrote, one for the path that found a different value and did nothing.
The bitwise and exchange operations also work on Atomic<bool>; fetch_add and
fetch_sub do not.
MemoryOrder
Section titled “MemoryOrder”Each operation takes a memory order that says how strict its ordering must be.
MemoryOrder has exactly five selectors:
MemoryOrder.relaxedMemoryOrder.acquireMemoryOrder.releaseMemoryOrder.acq_relMemoryOrder.seq_cst
Ordering rules
Section titled “Ordering rules”The compiler rejects orders that do not make sense:
- A
loadcannot usereleaseoracq_rel. - A
storecannot useacquireoracq_rel. - A
compare_exchangefailure order cannot userelease, and cannot be stronger than its success order.
Breaking any of these is a compile error.
Fences
Section titled “Fences”Atomic.fence(order) is a static call that orders memory without touching any one
cell. Its signature in the registry is:
Atomic<T>.fence(MemoryOrder)You call it on the type, naming the order at the call site:
Atomic.fence(MemoryOrder.seq_cst)Wait and notify
Section titled “Wait and notify”These let a thread sleep until a cell changes.
Atomic<T>.wait(T, MemoryOrder)Atomic<T>.wait_timeout(T, int, MemoryOrder) -> boolAtomic<T>.notify_one() -> intAtomic<T>.notify_all() -> intwait(expected, order)blocks while the cell still holdsexpected.wait_timeout(expected, nanos, order)waits up tonanosnanoseconds and returnstrueif it timed out.notify_one()wakes one waiter andnotify_all()wakes all of them; each returns how many were woken.
A wakeup is only a hint. Always recheck the value in a loop after waking.
Full example
Section titled “Full example”A relaxed counter run from two threads, then read back:
import std.ioimport std.thread
fn main() { let counter: Atomic<i64> = new Atomic<i64>(0)
let first: Thread<int> = thread.spawn(fn() -> int { var i: int = 0 for i < 10000 { counter.fetch_add(1, MemoryOrder.relaxed) i += 1 } return 0 }) let second: Thread<int> = thread.spawn(fn() -> int { var i: int = 0 for i < 10000 { counter.fetch_add(1, MemoryOrder.relaxed) i += 1 } return 0 }) first.join() second.join()
let took: bool = counter.compare_exchange(20000, 0, MemoryOrder.acq_rel, MemoryOrder.acquire) Atomic.fence(MemoryOrder.seq_cst) io.println("counted {counter.load(MemoryOrder.acquire)} reset {took}")}See also
Section titled “See also”- Ownership handles,
AtomicIntis a simpler, always sequentially consistent counter. - Concurrency, threads, channels, and locks.