pub struct Arc<T, A = Global>{ /* private fields */ }Expand description
A thread-safe reference-counting pointer. ‘Arc’ stands for ‘Atomically Reference Counted’.
The type Arc<T> provides shared ownership of a value of type T,
allocated in the heap. Invoking clone on Arc produces a new
Arc instance, which points to the same allocation on the heap as the
source Arc, while increasing a reference count. When the last Arc
pointer to a given allocation is destroyed, the value stored in that
allocation (often referred to as “inner value”) is also dropped.
Shared references in Rust disallow mutation by default, and Arc is no
exception: you cannot generally obtain a mutable reference to something
inside an Arc. If you do need to mutate through an Arc, you have several
options:
-
Use interior mutability with synchronization primitives like
Mutex,RwLock, or one of theAtomictypes. -
Use
Arc::get_mutwhen you know yourArcis not shared (has a reference count of 1), which provides direct mutable access to the inner value without any cloning.
use rune::sync::Arc;
use rune::alloc::try_vec;
let mut data = Arc::try_new(try_vec![1, 2, 3])?;
// This will clone the vector only if there are other references to it
Arc::get_mut(&mut data).unwrap().try_push(4)?;
assert_eq!(*data, try_vec![1, 2, 3, 4]);Note: This type is only available on platforms that support atomic loads
and stores of pointers, which includes all platforms that support the std
crate but not all those which only support alloc. This may be
detected at compile time using #[cfg(target_has_atomic = "ptr")].
§Thread Safety
Unlike Rc<T>, Arc<T> uses atomic operations for its reference counting.
This means that it is thread-safe. The disadvantage is that atomic
operations are more expensive than ordinary memory accesses. If you are not
sharing reference-counted allocations between threads, consider using
Rc<T> for lower overhead. Rc<T> is a safe default, because the compiler
will catch any attempt to send an Rc<T> between threads. However, a
library might choose Arc<T> in order to give library consumers more
flexibility.
Arc<T> will implement Send and Sync as long as the T implements
Send and Sync. Why can’t you put a non-thread-safe type T in an
Arc<T> to make it thread-safe? This may be a bit counter-intuitive at
first: after all, isn’t the point of Arc<T> thread safety? The key is
this: Arc<T> makes it thread safe to have multiple ownership of the same
data, but it doesn’t add thread safety to its data. Consider
Arc<RefCell<T>>. RefCell<T> isn’t Sync, and if
Arc<T> was always Send, Arc<RefCell<T>> would be as
well. But then we’d have a problem: RefCell<T> is not thread safe; it
keeps track of the borrowing count using non-atomic operations.
In the end, this means that you may need to pair Arc<T> with some sort of
std::sync type, usually Mutex<T>.
§Breaking cycles with Weak
The downgrade method can be used to create a non-owning
Weak pointer. A Weak pointer can be upgraded to an
Arc, but this will return None if the value stored in the allocation
has already been dropped. In other words, Weak pointers do not keep the
value inside the allocation alive; however, they do keep the allocation
(the backing store for the value) alive.
A cycle between Arc pointers will never be deallocated. For this reason,
Weak is used to break cycles. For example, a tree could have strong
Arc pointers from parent nodes to children, and Weak pointers from
children back to their parents.
§Cloning references
Creating a new reference from an existing reference-counted pointer is done
using the Clone trait implemented for Arc<T> and
Weak<T>.
use rune::sync::Arc;
use rune::alloc::try_vec;
let foo = Arc::try_new(try_vec![1.0, 2.0, 3.0])?;
// The two syntaxes below are equivalent.
let a = foo.clone();
let b = Arc::clone(&foo);
// a, b, and foo are all Arcs that point to the same memory location§Deref behavior
Arc<T> automatically dereferences to T (via the Deref trait), so you
can call T’s methods on a value of type Arc<T>. To avoid name clashes
with T’s methods, the methods of Arc<T> itself are associated functions,
called using fully qualified syntax:
use rune::sync::Arc;
let my_arc = Arc::try_new(())?;
let my_weak = Arc::downgrade(&my_arc);Arc<T>’s implementations of traits like Clone may also be called using
fully qualified syntax. Some people prefer to use fully qualified syntax,
while others prefer using method-call syntax.
use rune::sync::Arc;
let arc = Arc::try_new(())?;
// Method-call syntax
let arc2 = arc.clone();
// Fully qualified syntax
let arc3 = Arc::clone(&arc);Weak<T> does not auto-dereference to T, because the inner value
may have already been dropped.
§Examples
Sharing some immutable data between threads:
use std::thread;
use rune::sync::Arc;
let five = Arc::try_new(5)?;
for _ in 0..10 {
let five = Arc::clone(&five);
thread::spawn(move || {
println!("{five:?}");
});
}Sharing a mutable AtomicUsize:
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;
use rune::sync::Arc;
let val = Arc::try_new(AtomicUsize::new(5))?;
for _ in 0..10 {
let val = Arc::clone(&val);
thread::spawn(move || {
let v = val.fetch_add(1, Ordering::Relaxed);
println!("{v:?}");
});
}Implementations§
Source§impl<T> Arc<T>
impl<T> Arc<T>
Source§impl<T, A> Arc<T, A>
impl<T, A> Arc<T, A>
Sourcepub fn allocator(this: &Arc<T, A>) -> &A
pub fn allocator(this: &Arc<T, A>) -> &A
Returns a reference to the underlying allocator.
Note: this is an associated function, which means that you have to call
it as Arc::allocator(&a) instead of a.allocator(). This is so that
there is no conflict with a method on the inner type.
Sourcepub fn into_raw_with_allocator(this: Arc<T, A>) -> (*const T, A)
pub fn into_raw_with_allocator(this: Arc<T, A>) -> (*const T, A)
Consumes the Arc, returning the wrapped pointer and allocator.
To avoid a memory leak the pointer must be converted back to an Arc
using Arc::from_raw_in.
§Examples
use rune::alloc::prelude::*;
use rune::sync::Arc;
use rune::alloc::alloc::Global;
let x = Arc::try_new_in("hello".try_to_owned()?, Global)?;
let (ptr, alloc) = Arc::into_raw_with_allocator(x);
assert_eq!(unsafe { &*ptr }, "hello");
let x = unsafe { Arc::from_raw_in(ptr, alloc) };
assert_eq!(&*x, "hello");Sourcepub fn as_ptr(this: &Arc<T, A>) -> *const T
pub fn as_ptr(this: &Arc<T, A>) -> *const T
Provides a raw pointer to the data.
The counts are not affected in any way and the Arc is not consumed. The pointer is valid for
as long as there are strong counts in the Arc.
§Examples
use rune::alloc::prelude::*;
use rune::sync::Arc;
let x = Arc::try_new("hello".try_to_owned()?)?;
let y = Arc::clone(&x);
let x_ptr = Arc::as_ptr(&x);
assert_eq!(x_ptr, Arc::as_ptr(&y));
assert_eq!(unsafe { &*x_ptr }, "hello");Sourcepub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Arc<T, A>
pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Arc<T, A>
Constructs an Arc<T, A> from a raw pointer.
The raw pointer has the following requirements:
- If
Uis sized, it must have the same size and alignment asT. This is trivially true ifUisT. - If
Uis unsized, its data pointer must have the same size and alignment asT. This is trivially true ifArc<U>was constructed throughArc<T>and then converted toArc<U>through an unsized coercion.
Note that if U or U’s data pointer is not T but has the same size
and alignment, this is basically like transmuting references of
different types. See mem::transmute for more information on what
restrictions apply in this case.
The raw pointer must point to a block of memory allocated by alloc
The user of from_raw has to make sure a specific value of T is only
dropped once.
This function is unsafe because improper use may lead to memory
unsafety, even if the returned Arc<T> is never accessed.
§Safety
The pointer must point to an instance which has previously ben returned
by Arc<T>::into_raw_with_allocator. The allocator that was used must
also be compatible.
§Examples
use rune::alloc::prelude::*;
use rune::sync::Arc;
use rune::alloc::alloc::Global;
let x = Arc::try_new_in("hello".try_to_owned()?, Global)?;
let (x_ptr, alloc) = Arc::into_raw_with_allocator(x);
unsafe {
// Convert back to an `Arc` to prevent leak.
let x = Arc::from_raw_in(x_ptr, alloc);
assert_eq!(&*x, "hello");
// Further calls to `Arc::from_raw(x_ptr)` would be memory-unsafe.
}
// The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling!Convert a slice back into its original array:
use rune::sync::Arc;
let original: &[u8] = &[1, 2, 3];
let x: Arc<[u8]> = Arc::try_from(original)?;
let (x_ptr, alloc) = Arc::into_raw_with_allocator(x);
unsafe {
let x: Arc<[u8; 3], _> = Arc::from_raw_in(x_ptr.cast::<[u8; 3]>(), alloc);
assert_eq!(&*x, &[1, 2, 3]);
}Sourcepub fn ptr_eq(this: &Arc<T, A>, other: &Arc<T, A>) -> bool
pub fn ptr_eq(this: &Arc<T, A>, other: &Arc<T, A>) -> bool
Returns true if the two Arcs point to the same allocation in a vein
similar to ptr::eq. This function ignores the metadata of dyn Trait pointers.
§Examples
use rune::sync::Arc;
let five = Arc::try_new(5)?;
let same_five = Arc::clone(&five);
let other_five = Arc::try_new(5)?;
assert!(Arc::ptr_eq(&five, &same_five));
assert!(!Arc::ptr_eq(&five, &other_five));Sourcepub fn get_mut(this: &mut Arc<T, A>) -> Option<&mut T>
pub fn get_mut(this: &mut Arc<T, A>) -> Option<&mut T>
Returns a mutable reference into the given Arc, if there are
no other Arc or Weak pointers to the same allocation.
Returns None otherwise, because it is not safe to
mutate a shared value.
§Examples
use rune::sync::Arc;
let mut x = Arc::try_new(3)?;
*Arc::get_mut(&mut x).unwrap() = 4;
assert_eq!(*x, 4);
let _y = Arc::clone(&x);
assert!(Arc::get_mut(&mut x).is_none());Sourcepub unsafe fn get_mut_unchecked(this: &mut Arc<T, A>) -> &mut T
pub unsafe fn get_mut_unchecked(this: &mut Arc<T, A>) -> &mut T
Returns a mutable reference into the given Arc, without any check.
See also get_mut, which is safe and does appropriate checks.
§Safety
If any other Arc or Weak pointers to the same allocation exist,
then they must not be dereferenced or have active borrows for the
duration of the returned borrow, and their inner type must be exactly
the same as the inner type of this Rc (including lifetimes). This is
trivially the case if no such pointers exist, for example immediately
after Arc::new.
§Examples
use rune::sync::Arc;
use rune::alloc::String;
let mut x = Arc::try_new(String::new())?;
unsafe {
Arc::get_mut_unchecked(&mut x).try_push_str("foo")?
}
assert_eq!(*x, "foo");Other Arc pointers to the same allocation must be to the same type.
use rune::sync::Arc;
let x: Arc<str> = Arc::try_from("Hello, world!")?;
let mut y: Arc<[u8]> = x.clone().try_into()?;
unsafe {
// this is Undefined Behavior, because x's inner type is str, not [u8]
Arc::get_mut_unchecked(&mut y).fill(0xff); // 0xff is invalid in UTF-8
}
println!("{}", &*x); // Invalid UTF-8 in a strOther Arc pointers to the same allocation must be to the exact same
type, including lifetimes.
use rune::sync::Arc;
let x: Arc<&str> = Arc::try_new("Hello, world!")?;
{
let s = String::from("Oh, no!");
let mut y: Arc<&str> = x.clone();
unsafe {
// this is Undefined Behavior, because x's inner type
// is &'long str, not &'short str
*Arc::get_mut_unchecked(&mut y) = &s;
}
}
println!("{}", &*x); // Use-after-freeSourcepub fn is_unique(this: &Arc<T, A>) -> bool
pub fn is_unique(this: &Arc<T, A>) -> bool
Determine whether this is the unique reference to the underlying data.
Returns true if there are no other Arc or Weak pointers to the same allocation;
returns false otherwise.
If this function returns true, then is guaranteed to be safe to call get_mut_unchecked
on this Arc, so long as no clones occur in between.
§Examples
use rune::sync::Arc;
let x = Arc::try_new(3)?;
assert!(Arc::is_unique(&x));
let y = Arc::clone(&x);
assert!(!Arc::is_unique(&x));
drop(y);
// Weak references also count, because they could be upgraded at any time.
let z = Arc::downgrade(&x);
assert!(!Arc::is_unique(&x));§Pointer invalidation
This function will always return the same value as Arc::get_mut(arc).is_some(). However,
unlike that operation it does not produce any mutable references to the underlying data,
meaning no pointers to the data inside the Arc are invalidated by the call. Thus, the
following code is valid, even though it would be UB if it used Arc::get_mut:
use rune::sync::Arc;
let arc = Arc::try_new(5)?;
let pointer: *const i32 = &*arc;
assert!(Arc::is_unique(&arc));
assert_eq!(unsafe { *pointer }, 5);§Atomic orderings
Concurrent drops to other Arc pointers to the same allocation will synchronize with this
call - that is, this call performs an Acquire operation on the underlying strong and weak
ref counts. This ensures that calling get_mut_unchecked is safe.
Note that this operation requires locking the weak ref count, so concurrent calls to
downgrade may spin-loop for a short period of time.
Trait Implementations§
Source§impl<T, A> Clone for Arc<T, A>
impl<T, A> Clone for Arc<T, A>
Source§fn clone(&self) -> Arc<T, A>
fn clone(&self) -> Arc<T, A>
Makes a clone of the Arc pointer.
This creates another pointer to the same allocation, increasing the strong reference count.
§Examples
use rune::sync::Arc;
let five = Arc::try_new(5)?;
let _ = Arc::clone(&five);1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<'de, M, A, T> Decode<'de, M, A> for Arc<[T]>
impl<'de, M, A, T> Decode<'de, M, A> for Arc<[T]>
Source§const IS_BITWISE_DECODE: bool = false
const IS_BITWISE_DECODE: bool = false
Source§impl<'de, M, A, T> Decode<'de, M, A> for Arc<T>
impl<'de, M, A, T> Decode<'de, M, A> for Arc<T>
Source§const IS_BITWISE_DECODE: bool = false
const IS_BITWISE_DECODE: bool = false
Source§impl<'de, M, A> DecodeBytes<'de, M, A> for Arc<[u8]>where
A: Allocator,
impl<'de, M, A> DecodeBytes<'de, M, A> for Arc<[u8]>where
A: Allocator,
Source§const DECODE_BYTES_PACKED: bool = false
const DECODE_BYTES_PACKED: bool = false
Source§impl<'de, T> Deserialize<'de> for Arc<[T]>where
T: Deserialize<'de>,
impl<'de, T> Deserialize<'de> for Arc<[T]>where
T: Deserialize<'de>,
Source§fn deserialize<D>(
deserializer: D,
) -> Result<Arc<[T]>, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
deserializer: D,
) -> Result<Arc<[T]>, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
Source§impl<'de, T> Deserialize<'de> for Arc<T>where
T: Deserialize<'de>,
impl<'de, T> Deserialize<'de> for Arc<T>where
T: Deserialize<'de>,
Source§fn deserialize<D>(
deserializer: D,
) -> Result<Arc<T>, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
deserializer: D,
) -> Result<Arc<T>, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
Source§impl<T, A> Drop for Arc<T, A>
impl<T, A> Drop for Arc<T, A>
Source§fn drop(&mut self)
fn drop(&mut self)
Drops the Arc.
This will decrement the strong reference count. If the strong reference
count reaches zero then the only other references (if any) are
Weak, so we drop the inner value.
§Examples
use rune::sync::Arc;
struct Foo;
impl Drop for Foo {
fn drop(&mut self) {
println!("dropped!");
}
}
let foo = Arc::try_new(Foo)?;
let foo2 = Arc::clone(&foo);
drop(foo); // Doesn't print anything
drop(foo2); // Prints "dropped!"Source§impl<M, T> Encode<M> for Arc<T>
impl<M, T> Encode<M> for Arc<T>
Source§const IS_BITWISE_ENCODE: bool = false
const IS_BITWISE_ENCODE: bool = false
Source§fn encode<E>(&self, encoder: E) -> Result<(), <E as Encoder>::Error>where
E: Encoder<Mode = M>,
fn encode<E>(&self, encoder: E) -> Result<(), <E as Encoder>::Error>where
E: Encoder<Mode = M>,
Source§impl<T, A> Ord for Arc<T, A>
impl<T, A> Ord for Arc<T, A>
Source§fn cmp(&self, other: &Arc<T, A>) -> Ordering
fn cmp(&self, other: &Arc<T, A>) -> Ordering
Comparison for two Arcs.
The two are compared by calling cmp() on their inner values.
§Examples
use rune::sync::Arc;
use std::cmp::Ordering;
let five = Arc::try_new(5)?;
assert_eq!(Ordering::Less, five.cmp(&Arc::try_new(6)?));1.21.0 · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl<T, A> PartialEq for Arc<T, A>
impl<T, A> PartialEq for Arc<T, A>
Source§fn eq(&self, other: &Arc<T, A>) -> bool
fn eq(&self, other: &Arc<T, A>) -> bool
Equality for two Arcs.
Two Arcs are equal if their inner values are equal, even if they are
stored in different allocation.
If T also implements Eq (implying reflexivity of equality),
two Arcs that point to the same allocation are always equal.
§Examples
use rune::sync::Arc;
let five = Arc::try_new(5)?;
assert!(five == Arc::try_new(5)?);Source§fn ne(&self, other: &Arc<T, A>) -> bool
fn ne(&self, other: &Arc<T, A>) -> bool
Inequality for two Arcs.
Two Arcs are not equal if their inner values are not equal.
If T also implements Eq (implying reflexivity of equality),
two Arcs that point to the same value are always equal.
§Examples
use rune::sync::Arc;
let five = Arc::try_new(5)?;
assert!(five != Arc::try_new(6)?);Source§impl<T, A> PartialOrd for Arc<T, A>
impl<T, A> PartialOrd for Arc<T, A>
Source§fn partial_cmp(&self, other: &Arc<T, A>) -> Option<Ordering>
fn partial_cmp(&self, other: &Arc<T, A>) -> Option<Ordering>
Partial comparison for two Arcs.
The two are compared by calling partial_cmp() on their inner values.
§Examples
use std::cmp::Ordering;
use rune::sync::Arc;
let five = Arc::try_new(5)?;
assert_eq!(Some(Ordering::Less), five.partial_cmp(&Arc::try_new(6)?));Source§fn lt(&self, other: &Arc<T, A>) -> bool
fn lt(&self, other: &Arc<T, A>) -> bool
Less-than comparison for two Arcs.
The two are compared by calling < on their inner values.
§Examples
use rune::sync::Arc;
let five = Arc::try_new(5)?;
assert!(five < Arc::try_new(6)?);Source§fn le(&self, other: &Arc<T, A>) -> bool
fn le(&self, other: &Arc<T, A>) -> bool
‘Less than or equal to’ comparison for two Arcs.
The two are compared by calling <= on their inner values.
§Examples
use rune::sync::Arc;
let five = Arc::try_new(5)?;
assert!(five <= Arc::try_new(5)?);Source§impl<T> Serialize for Arc<T>
impl<T> Serialize for Arc<T>
Source§fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
Source§impl<A> TryFrom<&[u8]> for Arc<[u8], A>
impl<A> TryFrom<&[u8]> for Arc<[u8], A>
Source§fn try_from(
v: &[u8],
) -> Result<Arc<[u8], A>, <Arc<[u8], A> as TryFrom<&[u8]>>::Error>
fn try_from( v: &[u8], ) -> Result<Arc<[u8], A>, <Arc<[u8], A> as TryFrom<&[u8]>>::Error>
Allocates a reference-counted slice and fills it by cloning v’s items.
§Example
use rune::sync::Arc;
let original: &[u8] = &[1, 2, 3];
let shared: Arc<[u8]> = Arc::try_from(original)?;
assert_eq!(&[1, 2, 3], &shared[..]);Source§type Error = AllocError
type Error = AllocError
Source§impl<A> TryFrom<&str> for Arc<str, A>
impl<A> TryFrom<&str> for Arc<str, A>
Source§fn try_from(
v: &str,
) -> Result<Arc<str, A>, <Arc<str, A> as TryFrom<&str>>::Error>
fn try_from( v: &str, ) -> Result<Arc<str, A>, <Arc<str, A> as TryFrom<&str>>::Error>
Allocates a reference-counted str and copies v into it.
§Example
use rune::sync::Arc;
let shared: Arc<str> = Arc::try_from("eggplant")?;
assert_eq!("eggplant", &shared[..]);Source§type Error = AllocError
type Error = AllocError
Source§impl<T, A> TryFrom<Vec<T, A>> for Arc<[T], A>where
A: Allocator,
impl<T, A> TryFrom<Vec<T, A>> for Arc<[T], A>where
A: Allocator,
Source§fn try_from(
v: Vec<T, A>,
) -> Result<Arc<[T], A>, <Arc<[T], A> as TryFrom<Vec<T, A>>>::Error>
fn try_from( v: Vec<T, A>, ) -> Result<Arc<[T], A>, <Arc<[T], A> as TryFrom<Vec<T, A>>>::Error>
Allocates a reference-counted slice and moves v’s items into it.
§Example
use rune::sync::Arc;
use rune::alloc::{try_vec, Vec};
let unique: Vec<i32> = try_vec![1, 2, 3];
let shared: Arc<[i32]> = Arc::try_from(unique)?;
assert_eq!(&[1, 2, 3], &shared[..]);Source§type Error = AllocError
type Error = AllocError
impl<T, A> Eq for Arc<T, A>
impl<T, A> Send for Arc<T, A>
impl<T, A> Sync for Arc<T, A>
impl<T, A> UnwindSafe for Arc<T, A>
Auto Trait Implementations§
impl<T, A> Freeze for Arc<T, A>
impl<T, A> RefUnwindSafe for Arc<T, A>
impl<T, A> Unpin for Arc<T, A>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.