pub struct Arc<T> { /* private fields */ }
Expand description
The Arc<T>
type represents a thread-safe reference-counting pointer,
where “Arc” stands for “Atomically Reference Counted”. It provides shared
ownership of a value of type T, stored on the heap. When you call the clone
method on Arc, a new instance of Arc is created that points to the same heap
allocation as the original Arc, and the reference count is increased. Once
the last Arc pointer to a given allocation is destroyed, the inner value
stored in that allocation is also dropped.
Because shared references in Rust are read-only by default, you cannot modify the value stored inside an Arc. If you need to modify it, use the Mutex, RwLock, or one of the Atomic types.
Please note that 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 those that only support the alloc crate. You can check if a platform supports this type at compile time by using the #[cfg(target_has_atomic =“ptr”)] attribute.
§Thread Safety
Arc<T>
is a thread-safe reference-counting pointer, meaning it’s safe to
use in multithreaded environments. However, this comes at a cost, as atomic
operations are slower than regular memory accesses. If you’re not sharing
reference-counted values between threads, consider using
Rc<T>
instead, which has lower overhead.
Arc<T>
can be used with Send and Sync types only, so make sure that
the type T you’re using with it implements these traits. Keep in mind that
Arc<T>
only ensures thread safety for the reference count, not the data
stored in it. To make the data itself thread-safe, you may need to pair
Arc<T>
with a Send
+Sync
type, such as rclite::Mutex<T>
.
§Cloning references
Creating a new reference from an existing reference-counted pointer is done
using the Clone
trait implemented for Arc<T>
use rclite::Arc;
let foo = Arc::new(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
use rclite::Arc;
let arc = Arc::new(());
// Method-call syntax
let arc2 = arc.clone();
// Fully qualified syntax
let arc3 = Arc::clone(&arc);
Implementations§
Source§impl<T> Arc<T>
impl<T> Arc<T>
Sourcepub fn pin(data: T) -> Pin<Arc<T>>
pub fn pin(data: T) -> Pin<Arc<T>>
Constructs a new Pin<Arc<T>>
. If T
does not implement Unpin
, then
data
will be pinned in memory and unable to be moved.
Sourcepub fn as_ptr(&self) -> *const T
pub fn as_ptr(&self) -> *const T
Gives you a pointer to the data. The reference count stays the same and
the Arc<T>
isn’t used up. The pointer stays valid as long as there
are strong references to the Arc<T>
.
§Examples
use rclite::Arc;
let x = Arc::new("hello".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 fn into_raw(this: Self) -> *const T
pub fn into_raw(this: Self) -> *const T
Turns Arc<T>
into a raw pointer, must be converted back to
Arc<T>
with Arc::from_raw
to avoid memory leak.
§Examples
use rclite::Arc;
let x = Arc::new("hello".to_owned());
let x_ptr = Arc::into_raw(x);
assert_eq!(unsafe { &*x_ptr }, "hello");
// reconstruct arc to drop the reference and avoid memory leaks
unsafe { Arc::from_raw(x_ptr) };
Sourcepub unsafe fn from_raw(ptr: *const T) -> Self
pub unsafe fn from_raw(ptr: *const T) -> Self
Constructs an Arc<T>
from a raw pointer. The raw pointer must have
been from Arc<U>::into_raw
where U and T must have the same size
and alignment. Improper use may lead to memory unsafe operations.
§Safety
It’s only safe to construct back references that are generated with
Arc::into_raw
, converting any other references may lead to undefined
behaivior.
§Examples
use rclite::Arc;
let x = Arc::new("hello".to_owned());
let x_ptr = Arc::into_raw(x);
unsafe {
// Convert back to an [`Arc<T>`] to prevent leak.
let x = Arc::from_raw(x_ptr);
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!
Sourcepub fn strong_count(&self) -> usize
pub fn strong_count(&self) -> usize
Gets the number of strong pointers to an allocation. Be careful as another thread can change the count at any time.
§Examples
use rclite::Arc;
let five = Arc::new(5);
let _also_five = Arc::clone(&five);
// This assertion is deterministic because we haven't shared
// the [`Arc<T>`] between threads.
assert_eq!(2, Arc::strong_count(&five));
Sourcepub fn ptr_eq(this: &Self, other: &Self) -> bool
pub fn ptr_eq(this: &Self, other: &Self) -> bool
Compares if two Arcs reference the same allocation, similar to ptr::eq. Note: The same caveats apply when comparing dyn Trait pointers.
§Examples
use rclite::Arc;
let five = Arc::new(5);
let same_five = Arc::clone(&five);
let other_five = Arc::new(5);
assert!(Arc::ptr_eq(&five, &same_five));
assert!(!Arc::ptr_eq(&five, &other_five));
Sourcepub fn try_unwrap(this: Self) -> Result<T, Self>
pub fn try_unwrap(this: Self) -> Result<T, Self>
If there’s only one strong reference, returns the inner value. If not, returns an error with the Arc passed in.
§Examples
use rclite::Arc;
let x = Arc::new(3);
assert_eq!(Arc::try_unwrap(x).unwrap(), 3);
let x = Arc::new(4);
let _y = Arc::clone(&x);
assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4);
Sourcepub fn get_mut(this: &mut Self) -> Option<&mut T>
pub fn get_mut(this: &mut Self) -> Option<&mut T>
Returns a mutable reference to the inner value of the given Arc
if
this is the only Arc
pointing to it.
Returns None
otherwise because it is not safe to mutate a shared
value.
See also make_mut
, which clones the inner value when there
are other Arc
pointers.
§Examples
use rclite::Arc;
let mut x = Arc::new(3);
// Get a mutable reference to the inner value.
*Arc::get_mut(&mut x).unwrap() = 4;
assert_eq!(*x, 4);
// There are now two Arcs pointing to the same value, so `get_mut()` returns `None`.
let _y = Arc::clone(&x);
assert!(Arc::get_mut(&mut x).is_none());
Sourcepub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T
pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T
Returns a mutable reference into the given Arc
without checking if it
is safe to do so.
This method is faster than get_mut
since it avoids any runtime
checks. However, it is unsafe to use unless you can guarantee that
no other Arc
pointers to the same allocation exist and that they are
not dereferenced or have active borrows for the duration
of the returned borrow.
§Safety
You can use get_mut_unchecked
if all of the following conditions are
met:
- No other
Arc
pointers to the same allocation exist. - The inner type of all
Arc
pointers is exactly the same (including lifetimes). - No other
Arc
pointers are dereferenced or have active borrows for the duration of the returned mutable borrow.
These conditions are trivially satisfied immediately after creating a
new Arc
with Arc::new
.
§Examples
use rclite::Arc;
let mut x = Arc::new(String::new());
unsafe {
Arc::get_mut_unchecked(&mut x).push_str("foo")
}
assert_eq!(*x, "foo");
Sourcepub fn into_inner(this: Self) -> Option<T>
pub fn into_inner(this: Self) -> Option<T>
Returns the inner value of the Arc
if it’s the only strong reference.
If the Arc
has multiple strong references, None
is returned.
If Arc::into_inner
is called on every clone of this Arc
, exactly one
of the calls will return the inner value, ensuring it’s not dropped.
§Example
use rclite::Arc;
let x = Arc::new(3);
let y = Arc::clone(&x);
let x_thread = std::thread::spawn(|| Arc::into_inner(x));
let y_thread = std::thread::spawn(|| Arc::into_inner(y));
let x_inner_value = x_thread.join().unwrap();
let y_inner_value = y_thread.join().unwrap();
assert!(matches!(
(x_inner_value, y_inner_value),
(None, Some(3)) | (Some(3), None)
));
Source§impl<T: Clone> Arc<T>
impl<T: Clone> Arc<T>
Sourcepub fn unwrap_or_clone(this: Self) -> T
pub fn unwrap_or_clone(this: Self) -> T
If there is only one reference to T, removes it and returns it.
Otherwise, creates a copy of T and returns it. If rc_t
is an
Arc<T>
, this function behaves like calling (*rc_t).clone()
,
but avoids copying the value if possible.
§Examples
use rclite::Arc;
let inner = String::from("test");
let ptr = inner.as_ptr();
let rc = Arc::new(inner);
let inner = Arc::unwrap_or_clone(rc);
// The inner value was not cloned
assert_eq!(ptr, inner.as_ptr());
let rc = Arc::new(inner);
let rc2 = rc.clone();
let inner = Arc::unwrap_or_clone(rc);
// Because there were 2 references, we had to clone the inner value.
assert_ne!(ptr, inner.as_ptr());
// `rc2` is the last reference, so when we unwrap it we get back
// the original `String`.
let inner = Arc::unwrap_or_clone(rc2);
assert_eq!(ptr, inner.as_ptr());
Sourcepub fn make_mut(this: &mut Arc<T>) -> &mut T
pub fn make_mut(this: &mut Arc<T>) -> &mut T
Returns a mutable reference to the inner value of the given Arc
,
ensuring that it has unique ownership.
If there are other Arc
pointers to the same allocation, then
make_mut
will clone the inner value to a new allocation to ensure
unique ownership. This is also referred to as “clone-on-write”.
Unlike get_mut
, which only returns a mutable reference if there are no
other pointers to the same allocation, make_mut
always returns a
mutable reference to the unique allocation.
§Examples
use rclite::Arc;
let mut data = Arc::new(5);
*Arc::make_mut(&mut data) += 1; // Won't clone anything
let mut other_data = Arc::clone(&data); // Won't clone inner data
*Arc::make_mut(&mut data) += 1; // Clones inner data
*Arc::make_mut(&mut data) += 1; // Won't clone anything
*Arc::make_mut(&mut other_data) *= 2; // Won't clone anything
// Now `data` and `other_data` point to different allocations.
assert_eq!(*data, 8);
assert_eq!(*other_data, 12);
§See also
Trait Implementations§
Source§impl<T> AsRef<T> for Arc<T>
An implementation of the AsRef
trait for Arc<T>
.
impl<T> AsRef<T> for Arc<T>
An implementation of the AsRef
trait for Arc<T>
.
This allows an Arc<T>
to be treated as a reference to T
.
§Examples
use rclite::Arc;
let data = Arc::new(42);
let reference: &i32 = data.as_ref();
assert_eq!(*reference, 42);
Source§impl<T> Borrow<T> for Arc<T>
This trait allows for a value to be borrowed as a reference to a given type.
It is typically used for generic code that can work with borrowed values of
different types.
impl<T> Borrow<T> for Arc<T>
This trait allows for a value to be borrowed as a reference to a given type. It is typically used for generic code that can work with borrowed values of different types.
This implementation for Rc<T>
allows for an Rc<T>
to be borrowed as a
shared reference to T
.