arc
import std::alloc::arc; · source
Types
Arc<T, A>
type struct Arc<T, A = GlobalAlloc> where A: Allocator {
inner: ArcInner<T, A>*;
static new(value: T) -> Arc<T, GlobalAlloc>;
static new_in(value: T, alloc: A) -> Arc<T, A>;
static try_new(value: T) -> Result<Arc<T, GlobalAlloc>, AllocError>;
static try_new_in(value: T, alloc: A) -> Result<Arc<T, A>, AllocError>;
clone(&this) -> Arc<T, A>;
downgrade(&this) -> Weak<T, A>;
strong_count(&this) -> u64;
weak_count(&this) -> u64;
as_ptr(&this) -> T*;
get_ref(&this) -> T*;
get_mut(mut &this) -> Option<T*>;
into_raw(mut this) -> ArcInner<T, A>*;
static from_raw(p: ArcInner<T, A>*) -> Arc<T, A>;
static increment_strong_count(p: ArcInner<T, A>*) -> void;
static decrement_strong_count(p: ArcInner<T, A>*) -> void
where A: Allocator;
}
Shared ownership across threads. Arc is the thread-safe sibling of Rc. Same shape, same two-phase teardown, but the counts are Atomic<u64>, so handles can be cloned and dropped concurrently without a data race. It is structurally Send + Sync whenever T and A are.
import std::alloc::arc;
import std::thread;
mut shared: Arc<Table> = Arc::<Table>::new(table);
mut copy: Arc<Table> = shared.clone();
thread::spawn(worker, copy);
The API mirrors Rc — new, new_in, try_new, try_new_in, clone, downgrade, get_ref, get_mut, strong_count, weak_count — with upgrade on Weak running a compare-exchange loop so it can never resurrect a value whose strong count already reached zero.
get_mut requires strong == 1 && weak == 1. With a single strong reference no other thread holds an Arc to clone or downgrade from, so once both counts read 1 the access really is exclusive. Even then, interior mutation visible across threads needs the value itself to be Sync — an atomic, say.
Properties
| Property | Type |
|---|---|
inner | ArcInner<T, A>* |
Constructors
static new(value: T) -> Arc<T, GlobalAlloc>;
static new(value: T) -> Arc<T, GlobalAlloc>;Allocate a new Arc backed by GlobalAlloc with an initial count of 1. Panics on allocation failure; use try_new.
static new_in(value: T, alloc: A) -> Arc<T, A>;
static new_in(value: T, alloc: A) -> Arc<T, A>;Allocate with a caller-supplied allocator. Panics on failure.
static try_new(value: T) -> Result<Arc<T, GlobalAlloc>, AllocError>;
static try_new(value: T) -> Result<Arc<T, GlobalAlloc>, AllocError>;Fallible constructor backed by GlobalAlloc. Returns Err(AllocError) if the allocator refuses the request.
static try_new_in(value: T, alloc: A) -> Result<Arc<T, A>, AllocError>;
static try_new_in(value: T, alloc: A) -> Result<Arc<T, A>, AllocError>;Fallible constructor with a caller-supplied allocator. The allocator instance is stored in the inner header and is used to free the inner when the last reference drops.
static from_raw(p: ArcInner<T, A>*) -> Arc<T, A>;
static from_raw(p: ArcInner<T, A>*) -> Arc<T, A>;Reconstitute a handle from a pointer returned by into_raw, taking back ownership of exactly one strong reference; the returned handle's drop balances it. Undefined unless p came from into_raw (or an increment_strong_count) on an Arc<T, A> of this exact type whose reference has not already been balanced.
Static functions
static increment_strong_count(p: ArcInner<T, A>*) -> void;
static increment_strong_count(p: ArcInner<T, A>*) -> void;Add one to the strong count of an into_raw'd header held only as a raw pointer (no live handle). Pairs one-for-one with a later decrement_strong_count. Relaxed matches clone: the new owner already shares a happens-before edge with the caller.
static decrement_strong_count(p: ArcInner<T, A>*) -> void where A: Allocator;
static decrement_strong_count(p: ArcInner<T, A>*) -> void where A: Allocator;Remove one strong reference from a header held only as a raw pointer, running the value's destructor and freeing the header if it was the last. Balances one into_raw or increment_strong_count by routing through the handle Drop, so the release/acquire teardown ordering is identical. Undefined if the reference was already balanced.
Methods
clone(&this) -> Arc<T, A>;
clone(&this) -> Arc<T, A>;Produce another Arc pointing at the same value. The two handles are interchangeable; the strong count is incremented atomically with Relaxed ordering - the canonical reference-count pattern: the new owner already shares a happens-before with the cloning thread, so no further synchronization is needed at clone time.
downgrade(&this) -> Weak<T, A>;
downgrade(&this) -> Weak<T, A>;A non-owning Weak handle to the same value. Bumps the weak count (Relaxed suffices: the new Weak shares a happens-before with this thread already) but not the strong count.
strong_count(&this) -> u64;
strong_count(&this) -> u64;Current strong-reference count. Reads the atomic with SeqCst; treat this as advisory - by the time the caller uses the value another thread may have changed it.
weak_count(&this) -> u64;
weak_count(&this) -> u64;Number of live Weak handles (advisory). The strong group's shared unit is excluded, so this is 0 when no Weak has been created.
as_ptr(&this) -> T*;
as_ptr(&this) -> T*;Raw pointer to the shared value. Valid for as long as any strong clone of this Arc is still alive; dereferencing after the last drop is undefined.
get_ref(&this) -> T*;
get_ref(&this) -> T*;Shared borrow of the value. Sound for reads while any strong clone is alive. For mutation use get_mut (gated on uniqueness); note that even with unique ownership, interior mutation visible across threads needs the value itself to be Sync (e.g. an atomic).
get_mut(mut &this) -> Option<T*>;
get_mut(mut &this) -> Option<T*>;Mutable borrow only when this is the sole owner: exactly one strong reference AND no outstanding Weak (strong == 1 && weak == 1, both read with Acquire). With a single strong reference no other thread holds an Arc to clone or downgrade from, so once both counts read 1 the access is exclusive; otherwise None.
into_raw(mut this) -> ArcInner<T, A>*;
into_raw(mut this) -> ArcInner<T, A>*;Consume this handle without touching the strong count, yielding the raw header it referenced. The caller inherits the one strong reference this handle held and MUST later balance it - recover a handle with from_raw and drop it, or call decrement_strong_count - or the value leaks. The consumed handle's own drop is suppressed (its inner is nulled), so yielding the pointer here is not itself a decrement. Enables a raw ArcInner* to be parked in a void* slot (e.g. a manual-vtable waker) outside the type system while still owning a reference.
Weak<T, A>
type struct Weak<T, A = GlobalAlloc> {
inner: ArcInner<T, A>*;
static new() -> Weak<T, GlobalAlloc>;
upgrade(&this) -> Option<Arc<T, A>>;
clone(&this) -> Weak<T, A>;
strong_count(&this) -> u64;
}
The same shape as rc::Weak: it does not keep the value alive, upgrade returns None once the last strong handle is gone, and Weak::new() is the placeholder that never upgrades. The difference is that upgrade here is a compare-exchange loop, so it can never resurrect a value whose strong count another thread has already taken to zero.
Properties
| Property | Type |
|---|---|
inner | ArcInner<T, A>* |
Constructors
static new() -> Weak<T, GlobalAlloc>;
static new() -> Weak<T, GlobalAlloc>;A Weak that never upgrades. Allocates nothing; upgrade always returns None.
Methods
upgrade(&this) -> Option<Arc<T, A>>;
upgrade(&this) -> Option<Arc<T, A>>;Try to obtain a strong Arc. Returns None once the last strong reference has gone, or for a dangling Weak::new().
clone(&this) -> Weak<T, A>;
clone(&this) -> Weak<T, A>;Another Weak to the same value. Bumps the weak count.
strong_count(&this) -> u64;
strong_count(&this) -> u64;Live strong count, or 0 for a dangling Weak. Advisory.
The raw-pointer escape hatch
For parking a reference outside the type system — a manual-vtable waker, a C callback's void* — four statics operate on the header pointer directly:
into_rawconsumes a handle without touching the count.from_rawtakes the reference back as a handle.increment_strong_countadds one to a header held only as a raw pointer, asclonewould.decrement_strong_countremoves one, running the destructor and freeing the header if it was the last — asdropwould.
Each into_raw or increment_strong_count must be balanced exactly once by from_raw or decrement_strong_count, or the value leaks. Unbalancing in the other direction is undefined.
The memory ordering, briefly
type struct ArcInner<T, A> {
strong: Atomic<u64>;
weak: Atomic<u64>;
value: T;
alloc: A;
}
Clone bumps the count with Relaxed; drop decrements with Release and the last-decrement path issues an Acquire fence. This is the canonical Boost/Rust pattern. Relaxed is right for the clone because the new reference is only ever observed by callers who already share a happens-before edge with the cloning thread. The release/acquire pair on drop is what synchronizes the final T::drop() against every prior mutation from any thread that has already dropped its own handle.
Routing every free decision through the one atomic weak counter is what makes the race between "the last Arc drops" and "a Weak drops" safe: there is never a moment where two threads read two separate counters and both decide to free.
Properties
| Property | Type |
|---|---|
strong | Atomic<u64> |
weak | Atomic<u64> |
value | T |
alloc | A |
Trait implementations
Arc
implement<T, A> trait Drop for struct Arc<T, A> where A: Allocator
Weak
implement<T, A> trait Drop for struct Weak<T, A> where A: Allocator
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 Arc<T, A = GlobalAlloc> where A: Allocator {
inner: ArcInner<T, A>*;
}Arc<T, A>: atomic reference counting, with weak references.
type parameter Ttype parameter Awhere A: Allocator
type struct GlobalAlloc {}Zero-sized handle to the process-wide allocator. Construct with GlobalAlloc::new(); all instances dispatch through the same underlying backend.
where T: Ord + Clone, U: HashConstrains generic parameters to types that implement the listed traits, which is what makes those traits' methods callable on T. Bounds on one parameter join with +; parameters separate with ,. A where on a single method narrows the type's parameter for that method only.
type trait Allocator {
allocate(mut &this, layout: Layout) -> Result<NonNull<u8>, AllocError>;
deallocate(mut &this, ptr: NonNull<u8>, layout: Layout) -> void;
reallocate(mut &this, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<u8>, AllocError>;
}Allocator: the trait every heap strategy implements.
std::alloc::allocatorArc.inner: ArcInner<T, A>*type struct ArcInner<T, A> {
strong: Atomic<u64>;
weak: Atomic<u64>;
value: T;
alloc: A;
}Heap-resident header shared by every Arc<T, A> and Weak<T, A> for one value. The allocator instance lives here, not in the handles, so all of them agree on who frees the inner when the last reference drops.
type 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 Arc::new(value: T) -> Arc<T, GlobalAlloc>Allocate a new Arc backed by GlobalAlloc with an initial count of 1. Panics on allocation failure; use try_new.
(parameter) value: Ttype struct Arc<T, A = GlobalAlloc> where A: Allocator {
inner: ArcInner<T, A>*;
}Arc<T, A>: atomic reference counting, with weak references.
std::alloc::arcstatic Arc::new_in(value: T, alloc: A) -> Arc<T, A>Allocate with a caller-supplied allocator. Panics on failure.
(parameter) alloc: Astatic Arc::try_new(value: T) -> Result<Arc<T, GlobalAlloc>, AllocError>Fallible constructor backed by GlobalAlloc. Returns Err(AllocError) if the allocator refuses the request.
type struct AllocError {
kind: AllocErrorKind;
layout: Layout;
}static Arc::try_new_in(value: T, alloc: A) -> Result<Arc<T, A>, AllocError>Fallible constructor with a caller-supplied allocator. The allocator instance is stored in the inner header and is used to free the inner when the last reference drops.
Arc::clone(&this) -> Arc<T, A>Produce another Arc pointing at the same value. The two handles are interchangeable; the strong count is incremented atomically with Relaxed ordering - the canonical reference-count pattern: the new owner already shares a happens-before with the cloning thread, so no further synchronization is needed at clone time.
&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.
Arc::downgrade(&this) -> Weak<T, A>A non-owning Weak handle to the same value. Bumps the weak count (Relaxed suffices: the new Weak shares a happens-before with this thread already) but not the strong count.
type struct Weak<T, A = GlobalAlloc> {
inner: ArcInner<T, A>*;
}A non-owning reference to an Arc-managed value. Obtain one with Arc::downgrade; recover a strong Arc (if the value still lives) with upgrade. Holding a Weak keeps the header mapped but not the value.
Arc::strong_count(&this) -> u64Current strong-reference count. Reads the atomic with SeqCst; treat this as advisory - by the time the caller uses the value another thread may have changed it.
Arc::weak_count(&this) -> u64Number of live Weak handles (advisory). The strong group's shared unit is excluded, so this is 0 when no Weak has been created.
Arc::as_ptr(&this) -> T*Raw pointer to the shared value. Valid for as long as *any* strong clone of this Arc is still alive; dereferencing after the last drop is undefined.
Arc::get_ref(&this) -> T*Shared borrow of the value. Sound for reads while any strong clone is alive. For mutation use get_mut (gated on uniqueness); note that even with unique ownership, interior mutation visible across threads needs the value itself to be Sync (e.g. an atomic).
Arc::get_mut(mut &this) -> Option<T*>Mutable borrow only when this is the sole owner: exactly one strong reference AND no outstanding Weak (strong == 1 && weak == 1, both read with Acquire). With a single strong reference no other thread holds an Arc to clone or downgrade from, so once both counts read 1 the access is exclusive; otherwise None.
mut &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.
Arc::into_raw(mut this) -> ArcInner<T, A>*Consume this handle without touching the strong count, yielding the raw header it referenced. The caller inherits the one strong reference this handle held and MUST later balance it - recover a handle with from_raw and drop it, or call decrement_strong_count - or the value leaks.
mut thisA by-value receiver the body may also reassign. The receiver is moved into the method and consumed; the caller's value may not be used afterwards.
language referencestatic Arc::from_raw(p: ArcInner<T, A>*) -> Arc<T, A>Reconstitute a handle from a pointer returned by into_raw, taking back ownership of exactly one strong reference; the returned handle's drop balances it. Undefined unless p came from into_raw (or an increment_strong_count) on an Arc<T, A> of this exact type whose reference has not already been balanced.
(parameter) p: ArcInner<T, A>*static Arc::increment_strong_count(p: ArcInner<T, A>*) -> voidAdd one to the strong count of an into_raw'd header held only as a raw pointer (no live handle). Pairs one-for-one with a later decrement_strong_count. Relaxed matches clone: the new owner already shares a happens-before edge with the caller.
static Arc::decrement_strong_count(p: ArcInner<T, A>*) -> void
where A: AllocatorRemove one strong reference from a header held only as a raw pointer, running the value's destructor and freeing the header if it was the last. Balances one into_raw or increment_strong_count by routing through the handle Drop, so the release/acquire teardown ordering is identical.
import 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 shared: Arc<Table>static Arc::new(value: T) -> Arc<T, GlobalAlloc>Allocate a new Arc backed by GlobalAlloc with an initial count of 1. Panics on allocation failure; use try_new.
mut copy: Arc<Table>mut shared: Arc<Table>Arc::clone(&this) -> Arc<T, A>Produce another Arc pointing at the same value. The two handles are interchangeable; the strong count is incremented atomically with Relaxed ordering - the canonical reference-count pattern: the new owner already shares a happens-before with the cloning thread, so no further synchronization is needed at clone time.
function spawn<C, T>(ctx: C, body: (C) -> T) -> JoinHandle<T>
where C: Send, T: SendSpawn a thread that runs body(ctx) and returns a handle to its T result. ctx is moved into the new thread. body must be a function pointer or non-capturing lambda. Panics on allocation or pthread_create failure; use try_spawn for a fallible spawn.
mut copy: Arc<Table>type struct Weak<T, A = GlobalAlloc> {
inner: ArcInner<T, A>*;
}A non-owning reference to an Arc-managed value. Obtain one with Arc::downgrade; recover a strong Arc (if the value still lives) with upgrade. Holding a Weak keeps the header mapped but not the value.
type parameter AWeak.inner: ArcInner<T, A>*type parameter Ttype parameter Astatic Weak::new() -> Weak<T, GlobalAlloc>A Weak that never upgrades. Allocates nothing; upgrade always returns None.
Weak::upgrade(&this) -> Option<Arc<T, A>>Try to obtain a strong Arc. Returns None once the last strong reference has gone, or for a dangling Weak::new().
Weak::clone(&this) -> Weak<T, A>Another Weak to the same value. Bumps the weak count.
Weak::strong_count(&this) -> u64Live strong count, or 0 for a dangling Weak. Advisory.
type struct ArcInner<T, A> {
strong: Atomic<u64>;
weak: Atomic<u64>;
value: T;
alloc: A;
}Heap-resident header shared by every Arc<T, A> and Weak<T, A> for one value. The allocator instance lives here, not in the handles, so all of them agree on who frees the inner when the last reference drops.
ArcInner.strong: Atomic<u64>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.
ArcInner.weak: Atomic<u64>ArcInner.value: Ttype parameter TArcInner.alloc: Atype parameter Atype struct Rc<T, A = GlobalAlloc> where A: Allocator {
inner: RcInner<T, A>*;
}Rc<T, A>: single-threaded reference counting, with weak references.
std::alloc::rctype trait Send {}Types that are safe to transfer between threads. An owning value of a Send type may cross a thread boundary without violating memory safety.
type trait Sync {}Types that are safe to share between threads by shared reference. T: Sync if &T: Send.
new T { field: value }
new E::Variant(args)
new T[n]Heap allocation. new T { .. } places a struct literal on the heap and yields a T*, and new E::V(args) does the same for an enum variant; new T[n] reserves n uninitialised T - the typed malloc. The storage comes from T's Allocate implementation, or else the global allocator. Parentheses after a struct's name are refused (E0117): there are no constructors, and a struct's static new(..) is an ordinary method.
static Arc::new_in(value: T, alloc: A) -> Arc<T, A>Allocate with a caller-supplied allocator. Panics on failure.
std::alloc::arcstatic Arc::try_new(value: T) -> Result<Arc<T, GlobalAlloc>, AllocError>Fallible constructor backed by GlobalAlloc. Returns Err(AllocError) if the allocator refuses the request.
static Arc::try_new_in(value: T, alloc: A) -> Result<Arc<T, A>, AllocError>Fallible constructor with a caller-supplied allocator. The allocator instance is stored in the inner header and is used to free the inner when the last reference drops.
std::alloc::arcArc::downgrade(&this) -> Weak<T, A>A non-owning Weak handle to the same value. Bumps the weak count (Relaxed suffices: the new Weak shares a happens-before with this thread already) but not the strong count.
Arc::get_ref(&this) -> T*Shared borrow of the value. Sound for reads while any strong clone is alive. For mutation use get_mut (gated on uniqueness); note that even with unique ownership, interior mutation visible across threads needs the value itself to be Sync (e.g. an atomic).
Arc::get_mut(mut &this) -> Option<T*>Mutable borrow only when this is the sole owner: exactly one strong reference AND no outstanding Weak (strong == 1 && weak == 1, both read with Acquire). With a single strong reference no other thread holds an Arc to clone or downgrade from, so once both counts read 1 the access is exclusive; otherwise None.
Arc::strong_count(&this) -> u64Current strong-reference count. Reads the atomic with SeqCst; treat this as advisory - by the time the caller uses the value another thread may have changed it.
Arc::weak_count(&this) -> u64Number of live Weak handles (advisory). The strong group's shared unit is excluded, so this is 0 when no Weak has been created.
Weak::upgrade(&this) -> Option<Arc<T, A>>Try to obtain a strong Arc. Returns None once the last strong reference has gone, or for a dangling Weak::new().
ArcInner.strong: Atomic<u64>ArcInner.weak: Atomic<u64>Arc.inner: ArcInner<T, A>*Result::Err(E)static Arc::from_raw(p: ArcInner<T, A>*) -> Arc<T, A>Reconstitute a handle from a pointer returned by into_raw, taking back ownership of exactly one strong reference; the returned handle's drop balances it. Undefined unless p came from into_raw (or an increment_strong_count) on an Arc<T, A> of this exact type whose reference has not already been balanced.
Arc::into_raw(mut this) -> ArcInner<T, A>*Consume this handle without touching the strong count, yielding the raw header it referenced. The caller inherits the one strong reference this handle held and MUST later balance it - recover a handle with from_raw and drop it, or call decrement_strong_count - or the value leaks.
static Arc::increment_strong_count(p: ArcInner<T, A>*) -> voidAdd one to the strong count of an into_raw'd header held only as a raw pointer (no live handle). Pairs one-for-one with a later decrement_strong_count. Relaxed matches clone: the new owner already shares a happens-before edge with the caller.
static Arc::decrement_strong_count(p: ArcInner<T, A>*) -> void
where A: AllocatorRemove one strong reference from a header held only as a raw pointer, running the value's destructor and freeing the header if it was the last. Balances one into_raw or increment_strong_count by routing through the handle Drop, so the release/acquire teardown ordering is identical.
MemoryOrder::Relaxed = 2MemoryOrder::SeqCst = 7Arc::as_ptr(&this) -> T*Raw pointer to the shared value. Valid for as long as *any* strong clone of this Arc is still alive; dereferencing after the last drop is undefined.
MemoryOrder::Acquire = 4Option::Nonestatic Weak::new() -> Weak<T, GlobalAlloc>A Weak that never upgrades. Allocates nothing; upgrade always returns None.
MemoryOrder::Release = 5ArcInner.value: TArcInner.alloc: Aimplement 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.
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 reference