pub struct Atom<T: Send + Sync + 'static> { /* private fields */ }Expand description
A lock-free single-value container with safe memory reclamation.
Provides zero-overhead reads via load() and atomic writes
via store(), swap(), and
rcu(). Old values are automatically retired through
kovan’s wait-free reclamation.
Unlike ArcSwap, Atom<T> works with any T: Send + Sync + 'static —
there is no requirement to wrap values in Arc.
§Examples
use kovan::Atom;
// Create and read
let config = Atom::new(vec![1, 2, 3]);
assert_eq!(config.load().len(), 3);
// Atomic update — readers see old or new, never torn
config.store(vec![4, 5, 6, 7]);
assert_eq!(config.load().len(), 4);Implementations§
Source§impl<T: Send + Sync + 'static> Atom<T>
impl<T: Send + Sync + 'static> Atom<T>
Sourcepub fn new(val: T) -> Self
pub fn new(val: T) -> Self
Creates a new Atom containing val.
The value is heap-allocated and managed by kovan’s reclamation system.
§Examples
use kovan::Atom;
let atom = Atom::new(42);Sourcepub fn into_inner(self) -> T
pub fn into_inner(self) -> T
Consumes the Atom and returns the inner value.
This is safe because consuming self guarantees no concurrent access.
§Examples
use kovan::Atom;
let atom = Atom::new(String::from("hello"));
let s = atom.into_inner();
assert_eq!(s, "hello");Sourcepub fn load(&self) -> AtomGuard<'_, T>
pub fn load(&self) -> AtomGuard<'_, T>
Loads the current value, returning a guard that dereferences to &T.
This is the cheapest read operation — a single atomic load with
zero overhead. The returned AtomGuard keeps the value alive;
it will not be reclaimed until the guard is dropped.
§Consistency
Call load() once and reuse the guard for multiple accesses to
ensure you see a consistent snapshot. Calling load() multiple
times may return different values if another thread updated
the Atom in between.
§Examples
use kovan::Atom;
let atom = Atom::new(42);
let val = atom.load();
assert_eq!(*val, 42);Sourcepub fn load_clone(&self) -> Twhere
T: Clone,
pub fn load_clone(&self) -> Twhere
T: Clone,
Loads and clones the current value.
Equivalent to atom.load().clone() but expressed as a single call.
Use this when you need an owned copy and T: Clone.
§Examples
use kovan::Atom;
let atom = Atom::new(vec![1, 2, 3]);
let owned: Vec<i32> = atom.load_clone();Sourcepub fn peek<R>(&self, f: impl FnOnce(&T) -> R) -> R
pub fn peek<R>(&self, f: impl FnOnce(&T) -> R) -> R
Calls a closure with a reference to the current value.
This is useful when you want to inspect the value without holding onto a guard. The closure runs within a kovan critical section.
§Examples
use kovan::Atom;
let atom = Atom::new(vec![1, 2, 3]);
let len = atom.peek(|v| v.len());
assert_eq!(len, 3);Sourcepub fn store(&self, val: T)
pub fn store(&self, val: T)
Atomically replaces the current value.
The old value is retired for safe reclamation — it will be freed once no reader holds a guard referencing it.
§Examples
use kovan::Atom;
let atom = Atom::new(1);
atom.store(2);
assert_eq!(*atom.load(), 2);Sourcepub fn swap(&self, val: T) -> T
pub fn swap(&self, val: T) -> T
Atomically replaces the current value and returns the previous one.
Unlike store(), the old value is not retired —
ownership is transferred to the caller. The memory backing the old
node is retired for deallocation only (the value is moved out).
§Examples
use kovan::Atom;
let atom = Atom::new(String::from("hello"));
let old = atom.swap(String::from("world"));
assert_eq!(old, "hello");
assert_eq!(*atom.load(), "world");Sourcepub fn compare_and_swap<'a>(
&'a self,
current: &AtomGuard<'_, T>,
new: T,
) -> Result<AtomGuard<'a, T>, T>
pub fn compare_and_swap<'a>( &'a self, current: &AtomGuard<'_, T>, new: T, ) -> Result<AtomGuard<'a, T>, T>
Compare-and-swap: atomically replace the value if it hasn’t changed.
Loads the current pointer, compares it to current’s pointer. If they
match, stores new and retires the old value. Returns Ok(guard) with
the new value on success, or Err(new) returning the rejected value.
§Examples
use kovan::Atom;
let atom = Atom::new(1);
let current = atom.load();
// This succeeds because nobody changed it
assert!(atom.compare_and_swap(¤t, 2).is_ok());
assert_eq!(*atom.load(), 2);Sourcepub fn rcu<F>(&self, f: F)
pub fn rcu<F>(&self, f: F)
Read-Copy-Update: atomically apply a transformation.
Loads the current value, calls f(&T) to produce a new value,
then attempts a CAS. If another thread modified the value between
the load and CAS, the operation retries automatically.
The closure f may be called multiple times on contention.
Keep it cheap — do expensive work before calling rcu.
§Examples
use kovan::Atom;
let counter = Atom::new(0u64);
// Thread-safe increment (retries on contention)
counter.rcu(|val| val + 1);
assert_eq!(*counter.load(), 1);Sourcepub fn map<'a, R: 'a, F>(&'a self, f: F) -> AtomMap<'a, T, R, F>
pub fn map<'a, R: 'a, F>(&'a self, f: F) -> AtomMap<'a, T, R, F>
Create a mapped view that projects into a field of T.
Returns an AtomMap that loads T and applies f to project
into a sub-field. Useful for passing configuration sub-sections
to components without exposing the full T.
Keep f cheap — it runs on every load.
§Examples
use kovan::Atom;
struct Config { db_port: u16, workers: usize }
let config = Atom::new(Config { db_port: 5432, workers: 4 });
let port_view = config.map(|c| &c.db_port);
assert_eq!(*port_view.load(), 5432);