Skip to main content

Atom

Struct Atom 

Source
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>

Source

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);
Source

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");
Source

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);
Source

pub fn load_clone(&self) -> T
where 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();
Source

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);
Source

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);
Source

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");
Source

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(&current, 2).is_ok());
assert_eq!(*atom.load(), 2);
Source

pub fn rcu<F>(&self, f: F)
where F: FnMut(&T) -> T,

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);
Source

pub fn map<'a, R: 'a, F>(&'a self, f: F) -> AtomMap<'a, T, R, F>
where F: Fn(&T) -> &R,

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);

Trait Implementations§

Source§

impl<T: Send + Sync + 'static + Debug> Debug for Atom<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: Send + Sync + 'static + Default> Default for Atom<T>

Source§

fn default() -> Self

Creates an Atom containing T::default().

Source§

impl<T: Send + Sync + 'static> Drop for Atom<T>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl<T: Send + Sync + 'static> From<T> for Atom<T>

Source§

fn from(val: T) -> Self

Converts to this type from the input type.
Source§

impl<T: Send + Sync + 'static> Send for Atom<T>

Source§

impl<T: Send + Sync + 'static> Sync for Atom<T>

Auto Trait Implementations§

§

impl<T> !Freeze for Atom<T>

§

impl<T> RefUnwindSafe for Atom<T>
where T: RefUnwindSafe,

§

impl<T> Unpin for Atom<T>

§

impl<T> UnwindSafe for Atom<T>
where T: RefUnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<!> for T

Source§

fn from(t: !) -> T

Converts to this type from the input type.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.