pub struct OnceArc<T> { /* private fields */ }Expand description
A thread-safe container that can be atomically initialized once with an Arc<T>.
This is conceptually similar to Atomic<Option<Arc<T>>>, but with a critical restriction:
the value can only be set once. This restriction is what makes the implementation both
sound and extremely fast — load is a single atomic read with no reference count
manipulation.
§Examples
use std::sync::Arc;
use std::sync::atomic::Ordering;
use once_arc::OnceArc;
let slot: OnceArc<i32> = OnceArc::new();
assert!(slot.get(Ordering::Acquire).is_none());
slot.store(Arc::new(42), Ordering::Release).unwrap();
// get() returns &T — just a single atomic load
assert_eq!(slot.get(Ordering::Acquire), Some(&42));
// load() returns a cloned Arc
let arc = slot.load(Ordering::Acquire).unwrap();
assert_eq!(*arc, 42);
// Second store fails and returns the value back.
let err = slot.store(Arc::new(99), Ordering::Release).unwrap_err();
assert_eq!(*err, 99);Implementations§
Source§impl<T> OnceArc<T>
impl<T> OnceArc<T>
Sourcepub const fn new() -> Self
pub const fn new() -> Self
Creates a new empty OnceArc.
§Examples
use once_arc::OnceArc;
let slot: OnceArc<i32> = OnceArc::new();Sourcepub fn store(&self, value: Arc<T>, ordering: Ordering) -> Result<(), Arc<T>>
pub fn store(&self, value: Arc<T>, ordering: Ordering) -> Result<(), Arc<T>>
Attempts to store the value. Returns Ok(()) if this is the first call,
or Err(value) if a value was already stored.
ordering describes the required ordering for the
read-modify-write operation that takes place if the None-check succeeds.
Using Acquire as ordering makes the store part
of this operation Relaxed, and using Release makes the load Relaxed.
§Examples
use std::sync::Arc;
use std::sync::atomic::Ordering;
use once_arc::OnceArc;
let slot: OnceArc<i32> = OnceArc::new();
assert!(slot.store(Arc::new(42), Ordering::Release).is_ok());
// Second store fails
let err = slot.store(Arc::new(99), Ordering::Release).unwrap_err();
assert_eq!(*err, 99);Sourcepub fn get(&self, ordering: Ordering) -> Option<&T>
pub fn get(&self, ordering: Ordering) -> Option<&T>
Returns a reference to the stored value, or None if not yet set.
This is extremely fast: a single atomic load with no reference count
manipulation. The returned reference is valid for as long as &self is
valid, because the stored Arc is never removed until self is dropped.
§Examples
use std::sync::Arc;
use std::sync::atomic::Ordering;
use once_arc::OnceArc;
let slot: OnceArc<i32> = OnceArc::new();
assert_eq!(slot.get(Ordering::Acquire), None);
slot.store(Arc::new(42), Ordering::Release).unwrap();
assert_eq!(slot.get(Ordering::Acquire), Some(&42));Sourcepub fn load(&self, ordering: Ordering) -> Option<Arc<T>>
pub fn load(&self, ordering: Ordering) -> Option<Arc<T>>
Loads the stored value as a cloned Arc<T>. This increments the reference
count, so the caller gets an independent handle to the underlying data.
Returns None if the value has not been set yet.
§Examples
use std::sync::Arc;
use std::sync::atomic::Ordering;
use once_arc::OnceArc;
let slot = OnceArc::from(Arc::new(42));
let arc = slot.load(Ordering::Acquire).unwrap();
assert_eq!(*arc, 42);Sourcepub fn is_set(&self, ordering: Ordering) -> bool
pub fn is_set(&self, ordering: Ordering) -> bool
Returns true if a value has been stored.
§Examples
use std::sync::Arc;
use std::sync::atomic::Ordering;
use once_arc::OnceArc;
let slot: OnceArc<i32> = OnceArc::new();
assert!(!slot.is_set(Ordering::Relaxed));
slot.store(Arc::new(1), Ordering::Release).unwrap();
assert!(slot.is_set(Ordering::Relaxed));Sourcepub fn into_inner(self) -> Option<Arc<T>>
pub fn into_inner(self) -> Option<Arc<T>>
Consumes self and returns the stored Arc<T>, if any.
§Examples
use std::sync::Arc;
use std::sync::atomic::Ordering;
use once_arc::OnceArc;
let slot = OnceArc::from(Arc::new(42));
let arc = slot.into_inner().unwrap();
assert_eq!(*arc, 42);Sourcepub fn get_mut(&mut self) -> Option<&mut T>
pub fn get_mut(&mut self) -> Option<&mut T>
Returns a mutable reference to the stored value, or None if not yet set.
Since this requires &mut self, no atomic operations are needed and this
is guaranteed to be the only accessor.
§Examples
use std::sync::Arc;
use std::sync::atomic::Ordering;
use once_arc::OnceArc;
let mut slot = OnceArc::from(Arc::new(10));
*slot.get_mut().unwrap() = 20;
assert_eq!(slot.get(Ordering::Acquire), Some(&20));