atomic
import std::sync::atomic; · source
Types
Atomic<T>
type struct Atomic<T> {
value: T;
static new(initial: T) -> Atomic<T>;
load(&this, order: MemoryOrder) -> T;
store(mut &this, val: T, order: MemoryOrder) -> void;
fetch_add(mut &this, val: T, order: MemoryOrder) -> T;
fetch_sub(mut &this, val: T, order: MemoryOrder) -> T;
fetch_and(mut &this, val: T, order: MemoryOrder) -> T;
fetch_or(mut &this, val: T, order: MemoryOrder) -> T;
fetch_xor(mut &this, val: T, order: MemoryOrder) -> T;
swap(mut &this, val: T, order: MemoryOrder) -> T;
compare_exchange(mut &this, current: T, next: T, succ: MemoryOrder, fail: MemoryOrder) -> Result<T, T>;
}
One generic cell driven by the compiler's atomic intrinsics, which lower directly to LLVM's atomicrmw, cmpxchg, and atomic load/store. No libc, no spin loops, no calls.
import std::sync::atomic;
mut hits: Atomic<u64> = Atomic::<u64>::new(0);
hits.fetch_add(1, MemoryOrder::Relaxed);
const total: u64 = hits.load(MemoryOrder::SeqCst);
T is dispatched at compile time with static match (T), so Atomic::<u32>::load lowers to exactly the u32 atomic and nothing else. LLVM does not distinguish signed from unsigned for atomic integer memory operations, so the i32, i64, and boolean arms bitcast onto the same unsigned intrinsics.
Supported types are u8, u32, u64, i32, i64, and boolean. Instantiating Atomic<T> with anything else — or calling fetch_add on Atomic<boolean> — is a compile error (E0645). The absence of a matching static match arm is the type constraint; no trait bound is needed.
load and store take the ordering explicitly. The fetch_* family and swap return the previous value; compare_exchange(current, next, succ, fail) returns Ok(prev) when it swapped and Err(actual) on a mismatch.
Atomic cells are deliberately not
Copy. Mutation through a shared pointer has to stay explicit, and bitwise-copying an atomic would silently break that. Wrap inArc<Atomic<T>>to share.
Properties
| Property | Type |
|---|---|
value | T |
Constructors
static new(initial: T) -> Atomic<T>;
static new(initial: T) -> Atomic<T>;Construct an Atomic<T> initialized to initial. Stack-allocated; callers wishing to share between threads should wrap in Arc<Atomic<T>> or place inside a heap-pinned container.
Methods
load(&this, order: MemoryOrder) -> T;
store(mut &this, val: T, order: MemoryOrder) -> void;
fetch_add(mut &this, val: T, order: MemoryOrder) -> T;
fetch_add(mut &this, val: T, order: MemoryOrder) -> T;Atomically add val to the cell and return the previous value.
fetch_sub(mut &this, val: T, order: MemoryOrder) -> T;
fetch_sub(mut &this, val: T, order: MemoryOrder) -> T;Atomically subtract val from the cell and return the previous value. See fetch_add for the Atomic<boolean> caveat.
fetch_and(mut &this, val: T, order: MemoryOrder) -> T;
fetch_and(mut &this, val: T, order: MemoryOrder) -> T;AND the cell with val. Returns the previous value.
fetch_or(mut &this, val: T, order: MemoryOrder) -> T;
fetch_or(mut &this, val: T, order: MemoryOrder) -> T;OR the cell with val. Returns the previous value.
fetch_xor(mut &this, val: T, order: MemoryOrder) -> T;
fetch_xor(mut &this, val: T, order: MemoryOrder) -> T;XOR the cell with val. Returns the previous value.
swap(mut &this, val: T, order: MemoryOrder) -> T;
swap(mut &this, val: T, order: MemoryOrder) -> T;Atomically replace the cell's value with val and return the previous value.
compare_exchange(mut &this, current: T, next: T, succ: MemoryOrder, fail: MemoryOrder) -> Result<T, T>;
compare_exchange(mut &this, current: T, next: T, succ: MemoryOrder, fail: MemoryOrder) -> Result<T, T>;Atomic compare-and-swap. Returns Ok(prev) with prev == current when the swap happens; Err(actual) with the observed value when the comparison fails.
Trait implementations
implement<T> trait Drop for struct Atomic<T>
A no-op; it exists so Atomic<T> satisfies T: Drop bounds inside containers.
MemoryOrder
type enum MemoryOrder : u32 {
Relaxed = 2;
Acquire = 4;
Release = 5;
AcqRel = 6;
SeqCst = 7;
}
implement enum MemoryOrder {
static to_u32(order: MemoryOrder) -> u32;
}
When in doubt, SeqCst is always safe. A load cannot use Release. The numeric values are LLVM's ordering codes, which is why the enum starts at 2; the name avoids clashing with core::cmp::Ordering.
Variants
| Variant |
|---|
Relaxed = 2 |
Acquire = 4 |
Release = 5 |
AcqRel = 6 |
SeqCst = 7 |
Static functions
static to_u32(order: MemoryOrder) -> u32;
Free Functions
Fences
fence(order) emits a real LLVM fence. Because a Relaxed fence would be meaningless, a weaker request is clamped up to SeqCst rather than producing invalid IR. compiler_fence(order) is for constraining the compiler's reordering rather than the CPU's — signal handlers, longjmp paths — though today it conservatively lowers to a real fence too.
function fence(order: MemoryOrder) -> void;
function fence(order: MemoryOrder) -> void;Insert a memory fence with the given ordering. Equivalent to atomicrmw xchg on a dummy location with no actual ops, but generated as a real LLVM fence instruction.
function compiler_fence(order: MemoryOrder) -> void;
function compiler_fence(order: MemoryOrder) -> void;Like fence, but intended only to constrain the compiler's reordering, not the CPU's. Today this conservatively lowers to a real LLVM fence at the requested ordering (so it also bars CPU reordering); the lighter semantics are preserved in the signature for future refinement. Use this when communicating with code inside the same thread (e.g., signal handlers, longjmp paths).
type struct Name { ... }
type enum Name { ... }
type trait Name { ... }
type union Name { ... }Begins a type declaration; the keyword that follows says which kind. On its own, type Name = Existing; declares an alias.
type struct Name {
field: Type;
method(&this) -> Ret { ... }
}A value type with named fields and optional methods. Structs live on the stack and are passed by value. Fields are public by default and may carry = default values; methods take their receiver as &this, mut &this, or this.
type struct Atomic<T> {
value: T;
}A single atomic cell of type T. See the module docs for the supported T and the compile-time dispatch model.
type parameter TAtomic.value: Ttype parameter Tstatic name(param: Type) -> Ret { ... }A method that belongs to the type rather than an instance, called as Type::name(..). For structs, static new(..) returning a struct literal is the idiomatic constructor.
static Atomic::new(initial: T) -> Atomic<T>Construct an Atomic<T> initialized to initial. Stack-allocated; callers wishing to share between threads should wrap in Arc<Atomic<T>> or place inside a heap-pinned container.
(parameter) initial: Ttype struct Atomic<T> {
value: T;
}A single atomic cell of type T. See the module docs for the supported T and the compile-time dispatch model.
Atomic::load(&this, order: MemoryOrder) -> T&this
mut &this
thisThe receiver of a method. Its first parameter declares how the method takes it: &this borrows read-only, mut &this borrows exclusively, and this / mut this move the value in and consume it. In the body, this.field reaches the members.
(parameter) order: MemoryOrdertype enum MemoryOrder : u32 {
Relaxed = 2;
Acquire = 4;
Release = 5;
AcqRel = 6;
SeqCst = 7;
}Memory-ordering for an atomic operation.
std::sync::atomicAtomic::store(mut &this, val: T, order: MemoryOrder) -> voidmut &this
mut &TypeAn exclusive, mutating borrow. As a receiver, mut &this lets the method modify the fields - and callers can see that from the signature alone. As a parameter type, mut &T lets the callee mutate through the reference while the caller keeps ownership.
(parameter) val: TAtomic::fetch_add(mut &this, val: T, order: MemoryOrder) -> TAtomically add val to the cell and return the previous value.
Atomic::fetch_sub(mut &this, val: T, order: MemoryOrder) -> TAtomically subtract val from the cell and return the previous value. See fetch_add for the Atomic<boolean> caveat.
Atomic::fetch_and(mut &this, val: T, order: MemoryOrder) -> TAND the cell with val. Returns the previous value.
Atomic::fetch_or(mut &this, val: T, order: MemoryOrder) -> TOR the cell with val. Returns the previous value.
Atomic::fetch_xor(mut &this, val: T, order: MemoryOrder) -> TXOR the cell with val. Returns the previous value.
Atomic::swap(mut &this, val: T, order: MemoryOrder) -> TAtomically replace the cell's value with val and return the previous value.
Atomic::compare_exchange(mut &this, current: T, next: T, succ: MemoryOrder, fail: MemoryOrder) -> Result<T, T>Atomic compare-and-swap. Returns Ok(prev) with prev == current when the swap happens; Err(actual) with the observed value when the comparison fails.
(parameter) current: T(parameter) next: T(parameter) succ: MemoryOrder(parameter) fail: MemoryOrderimport a::b;
import a::b::{ X, Y };
import a::b as c;
import a::b::*;Brings a module, or selected items from it, into scope. One path per declaration: use the brace form for several items, as to alias, and * for everything public (prefer the brace form; wildcards invite name collisions).
mut name: Type = value;A mutable binding, reassignable after declaration - mutability is opt-in, const is the default. At module level it declares mutable global state. Before & it marks an exclusive reference or receiver instead.
mut hits: Atomic<u64>static Atomic::new(initial: T) -> Atomic<T>Construct an Atomic<T> initialized to initial. Stack-allocated; callers wishing to share between threads should wrap in Arc<Atomic<T>> or place inside a heap-pinned container.
mut hits: Atomic<u64>Atomic::fetch_add(mut &this, val: T, order: MemoryOrder) -> TAtomically add val to the cell and return the previous value.
MemoryOrder::Relaxed = 2const NAME: Type = value;At module level, a true compile-time constant, conventionally SCREAMING_SNAKE_CASE. (mut at module level declares mutable global state instead.)
const total: u64Atomic::load(&this, order: MemoryOrder) -> TMemoryOrder::SeqCst = 7type enum Name {
Unit,
Payload(T),
Named { x: i32 },
}An algebraic data type. Variants may be bare or carry a tuple or struct payload, and a match on an enum must cover every variant. Name::Variant names a variant; methods are added with implement enum Name { ... }.
type enum MemoryOrder : u32 {
Relaxed = 2;
Acquire = 4;
Release = 5;
AcqRel = 6;
SeqCst = 7;
}Memory-ordering for an atomic operation.
MemoryOrder::Relaxed = 2MemoryOrder::Acquire = 4MemoryOrder::Release = 5MemoryOrder::AcqRel = 6MemoryOrder::SeqCst = 7implement struct Name { ... }
implement trait Trait for Type { ... }
implement u64 { ... }Adds methods to a type outside its declaration. implement struct T (or enum, or a bare primitive) opens an inherent block; implement trait Tr for T supplies a trait's methods for one type. Resolution is at compile time - no dynamic dispatch.
implement enum Name { ... }Names the enum an inherent block extends - the only way to give an enum methods.
language referencestatic MemoryOrder::to_u32(order: MemoryOrder) -> u32static match (T) { ... }Opens a compile-time match on a type parameter: the one arm whose type matches is kept during monomorphisation and the rest are discarded.
static match (T) {
u8 | u16 => { ... }
_ => { ... }
}Selects a body by inspecting a type parameter at compile time. The subject is a type and each arm is a type (| groups several; _ takes the rest). During monomorphisation the one matching arm is kept and the others discarded, so there is no runtime branch.
Atomic::store(mut &this, val: T, order: MemoryOrder) -> voidAtomic::swap(mut &this, val: T, order: MemoryOrder) -> TAtomically replace the cell's value with val and return the previous value.
Atomic::compare_exchange(mut &this, current: T, next: T, succ: MemoryOrder, fail: MemoryOrder) -> Result<T, T>Atomic compare-and-swap. Returns Ok(prev) with prev == current when the swap happens; Err(actual) with the observed value when the comparison fails.
Result::Ok(T)Result::Err(E)type trait Copy {}Types whose values can be duplicated by a bitwise copy. Integers, floats, pointers, and pure-POD structs qualify; anything that owns resources (heap storage, file handles, refcount) does not.
std::core::markertype struct Arc<T, A = GlobalAlloc> where A: Allocator {
inner: ArcInner<T, A>*;
}Arc<T, A>: atomic reference counting, with weak references.
std::alloc::arcAtomic.value: TAtomic::fetch_sub(mut &this, val: T, order: MemoryOrder) -> TAtomically subtract val from the cell and return the previous value. See fetch_add for the Atomic<boolean> caveat.
Atomic::fetch_and(mut &this, val: T, order: MemoryOrder) -> TAND the cell with val. Returns the previous value.
Atomic::fetch_or(mut &this, val: T, order: MemoryOrder) -> TOR the cell with val. Returns the previous value.
Atomic::fetch_xor(mut &this, val: T, order: MemoryOrder) -> TXOR the cell with val. Returns the previous value.
type trait Name : Base {
method(&this, other: &This) -> Ret;
}Names a set of methods a type may implement. Inside the body This is the implementing type; methods may carry default bodies, and a trait may require a base trait (type trait Ord : Eq). Generic code asks for a trait with where T: Name.
implement trait Trait for Type { ... }Names the type a trait implementation is for. The block that follows supplies the bodies the trait requires.
language referenceMemoryOrder::Release = 5type enum Ordering {
Less;
Equal;
Greater;
}MemoryOrder::Acquire = 4MemoryOrder::AcqRel = 6static MemoryOrder::to_u32(order: MemoryOrder) -> u32function fence(order: MemoryOrder) -> voidInsert a memory fence with the given ordering. Equivalent to atomicrmw xchg on a dummy location with no actual ops, but generated as a real LLVM fence instruction.
function compiler_fence(order: MemoryOrder) -> voidLike fence, but intended only to constrain the compiler's reordering, not the CPU's. Today this conservatively lowers to a real LLVM fence at the requested ordering (so it also bars CPU reordering); the lighter semantics are preserved in the signature for future refinement.
function name<T>(param: Type) -> Ret { ... }Declares a function. Parameters are written name: Type and are never inferred; the return type follows -> and defaults to void. Declaration order does not matter: every signature is collected before any body is checked, so functions may call each other freely and recurse.
function fence(order: MemoryOrder) -> voidInsert a memory fence with the given ordering. Equivalent to atomicrmw xchg on a dummy location with no actual ops, but generated as a real LLVM fence instruction.
function compiler_fence(order: MemoryOrder) -> voidLike fence, but intended only to constrain the compiler's reordering, not the CPU's. Today this conservatively lowers to a real LLVM fence at the requested ordering (so it also bars CPU reordering); the lighter semantics are preserved in the signature for future refinement.