AtomicCell

Struct AtomicCell 

Source
pub struct AtomicCell<T, A: AtomicStorage> { /* private fields */ }
Expand description

A thread-safe mutable memory location.

This type is equivalent to Cell, except it can also be shared among multiple threads.

Operations on AtomicCells use atomic instructions with Acquire ordering for loads and Release ordering for stores. Choice of A selects what atomic storage and instructions are used.

§Drop

A::drop is frequently avoided, instead AtomicStorage::into_inner is often called. When a AtomicCell is dropped, AtomicStorage::forgettable is called, and then inner T value is extracted before T::drop is called.

§Panics

All functions will panic if T cannot be supported by A.

Implementations§

Source§

impl<T, A: AtomicStorage> AtomicCell<UnderlyingMarker<T>, StorageMarker<A>>

Source

pub fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::generic::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::generic::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::generic::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::generic::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> A::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::generic::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::generic::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, A::Underlying)

Get a raw copy of a value (useful for compare_update_raw).

§Examples
use atomic_cell::generic::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: A::Underlying, new: T, ) -> Result<T, (T, A::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<A::Underlying, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default, A: AtomicStorage> AtomicCell<UnderlyingMarker<T>, StorageMarker<A>>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::generic::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy, A: AtomicStorage> AtomicCell<UnderlyingMarker<T>, StorageMarker<A>>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::generic::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq, A: AtomicStorage> AtomicCell<UnderlyingMarker<T>, StorageMarker<A>>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::generic::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<P, T> AtomicCell<T, AtomicPtr<P>>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicPtr<P> as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicPtr<P> as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicPtr<P> as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicPtr<P> as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<P, T: Default> AtomicCell<T, AtomicPtr<P>>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<P, T: Copy> AtomicCell<T, AtomicPtr<P>>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<P, T: Copy + PartialEq> AtomicCell<T, AtomicPtr<P>>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T> AtomicCell<T, AtomicUsize>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicUsize as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicUsize as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicUsize as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicUsize as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default> AtomicCell<T, AtomicUsize>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy> AtomicCell<T, AtomicUsize>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq> AtomicCell<T, AtomicUsize>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T> AtomicCell<T, AtomicIsize>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicIsize as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicIsize as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicIsize as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicIsize as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default> AtomicCell<T, AtomicIsize>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy> AtomicCell<T, AtomicIsize>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq> AtomicCell<T, AtomicIsize>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T> AtomicCell<T, AtomicU64>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicU64 as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicU64 as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicU64 as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicU64 as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default> AtomicCell<T, AtomicU64>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy> AtomicCell<T, AtomicU64>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq> AtomicCell<T, AtomicU64>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T> AtomicCell<T, AtomicI64>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicI64 as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicI64 as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicI64 as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicI64 as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default> AtomicCell<T, AtomicI64>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy> AtomicCell<T, AtomicI64>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq> AtomicCell<T, AtomicI64>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T> AtomicCell<T, AtomicU32>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicU32 as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicU32 as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicU32 as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicU32 as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default> AtomicCell<T, AtomicU32>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy> AtomicCell<T, AtomicU32>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq> AtomicCell<T, AtomicU32>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T> AtomicCell<T, AtomicI32>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicI32 as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicI32 as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicI32 as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicI32 as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default> AtomicCell<T, AtomicI32>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy> AtomicCell<T, AtomicI32>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq> AtomicCell<T, AtomicI32>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T> AtomicCell<T, AtomicU16>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicU16 as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicU16 as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicU16 as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicU16 as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default> AtomicCell<T, AtomicU16>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy> AtomicCell<T, AtomicU16>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq> AtomicCell<T, AtomicU16>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T> AtomicCell<T, AtomicI16>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicI16 as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicI16 as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicI16 as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicI16 as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default> AtomicCell<T, AtomicI16>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy> AtomicCell<T, AtomicI16>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq> AtomicCell<T, AtomicI16>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T> AtomicCell<T, AtomicU8>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicU8 as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicU8 as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicU8 as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicU8 as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default> AtomicCell<T, AtomicU8>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy> AtomicCell<T, AtomicU8>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq> AtomicCell<T, AtomicU8>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T> AtomicCell<T, AtomicI8>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicI8 as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicI8 as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicI8 as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicI8 as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default> AtomicCell<T, AtomicI8>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy> AtomicCell<T, AtomicI8>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq> AtomicCell<T, AtomicI8>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T> AtomicCell<T, AtomicBool>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicBool as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicBool as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicBool as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicBool as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default> AtomicCell<T, AtomicBool>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy> AtomicCell<T, AtomicBool>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq> AtomicCell<T, AtomicBool>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T> AtomicCell<T, AtomicUnit>

Source

pub const fn new(val: T) -> Self

Creates a new atomic cell initialized with val.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
Source

pub fn into_inner(self) -> T

Consumes the atomic and returns the contained value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);
let v = a.into_inner();

assert_eq!(v, 7);
Source

pub fn get_mut(&mut self) -> &mut T

Returns a mutable reference to contained data.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

let mut a = AtomicCell::<_, AtomicU32>::new(NonZeroU32::new(7));
assert_eq!(*a.get_mut(), NonZeroU32::new(7));
*a.get_mut() = NonZeroU32::new(12);
assert_eq!(a.load(), NonZeroU32::new(12));
Source

pub fn store(&self, val: T)

Stores val into the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
a.store(8);
assert_eq!(a.load(), 8);
Source

pub fn load_raw(&self) -> <AtomicUnit as AtomicStorageBase>::Underlying

Load a raw value from the the atomic cell. These raw values are not guaranteed to be safe to transmute, but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are returned, they are no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

struct NoCopy(u32);

let a = AtomicCell::<_, AtomicU32>::new(NoCopy(7));

assert_eq!(a.load_raw(), 7);
Source

pub fn swap(&self, val: T) -> T

Stores val into the atomic cell and returns the previous value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
Source

pub fn get_raw(val: T) -> (T, <AtomicUnit as AtomicStorageBase>::Underlying)

Get a raw copy of a value (useful for Self::compare_update_raw).

§Examples
use atomic_cell::macros::AtomicCell;
use std::num::NonZeroU32;
use std::sync::atomic::AtomicU32;

assert_eq!(AtomicCell::<_, AtomicU32>::get_raw(7).1, 7);
assert_eq!(
    AtomicCell::<Option<NonZeroU32>, AtomicU32>::get_raw(None).1,
    0
);
assert_eq!(
    AtomicCell::<_, AtomicU32>::get_raw(NonZeroU32::new(5)).1,
    5
);
Source

pub fn compare_exchange_raw<const WEAK: bool>( &self, current: <AtomicUnit as AtomicStorageBase>::Underlying, new: T, ) -> Result<T, (T, <AtomicUnit as AtomicStorageBase>::Underlying)>

The return value is a result indicating whether the new value was written. On success, this contains the previous value and is guaranteed to be equal to current. On failure, this contains new and the value currently stored in `Raw

If WEAK is set, this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

Source

pub fn compare_update_raw<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is $a::Underlying. There are no special restrictions on the raw values returned by CompareUpdate::initial. The raw value passed to CompareUpdate::retry is the most recently read raw value from the cell. These raw values are not guaranteed to be safe to transmute (unless T is Copy), but do have a guarantee of byte equivalency to a previously safe value been safe to transmute at one point. By the time these values are passed to f, they may no longer safe (e.g. if the value is a pointer, the memory pointed to may already be freed).

§Examples
use atomic_cell::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

let v: Result<_, ()> = a.compare_update_raw::<_, true>((
    (),      // No retry data
    7,       // The expected current raw value
    8,       // The initial value to try to swap in
    |(), _raw, _val| Ok((
        (),  // No retry data
        14,  // Value to-be-swapped-in on retries
    )),
));
assert_eq!(v, Ok(7));    // The swapped value
assert_eq!(a.load(), 8);

let v = a.compare_update_raw::<_, true>((
    "hello", // Arbitrary retry data
    5,                              // Cell contains `8`, so passing `5` will result in at least 1 closure invocation
    42,
    |c, raw, _val| match (c, raw) {
        // The cell contains an 8, not a 5, so now let's fail
        ("hello", 8) => Err("arbitrary error"),
        (c, v) => panic!("unexpected value ({}, {})", c, v),
    },
));
assert_eq!(v, Err("arbitrary error"));
assert_eq!(a.load(), 8);

T::drop can be avoided quite easily.

use atomic_cell::AtomicCell;
use std::mem::drop;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering::Relaxed};

static DROPPED: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Dropper(u32);
impl Drop for Dropper {
    fn drop(&mut self) {
        DROPPED.fetch_add(1, Relaxed);
    }
}

let a = AtomicCell::<_, AtomicPtr<Dropper>>::new(Some(Box::new(Dropper(5))));
let raw_none = AtomicCell::<Option<Box<Dropper>>, AtomicPtr<Dropper>>::get_raw(None).1;

// Try (should fail) to swap out `None` while only allocating once
let v = Some(Box::new(Dropper(6)));
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw: *mut Dropper, v| {
    if raw == raw_none {
        Ok(((), v))      // Keep trying with `v`
    } else {
        Err(v)           // Abort, saving the data
    }
}));

// Retreive the allocation from the error
let v = v.expect_err("compare_update_raw should have aborted");

// Drop the value in the cell
assert_eq!(DROPPED.load(Relaxed), 0);
a.store(None);
assert_eq!(DROPPED.load(Relaxed), 1);

// Try to swap again, using the same allocation
let v = a.compare_update_raw::<_, true>(((), raw_none, v, |(), raw, v| {
    if raw == raw_none {
        Ok(((), v))
    } else {
        Err(v)
    }
}));
let v = v.expect("compare_update_raw should have succeeded");
assert!(v.is_none());

assert_eq!(DROPPED.load(Relaxed), 1);
drop(a);
assert_eq!(DROPPED.load(Relaxed), 2);
Source§

impl<T: Default> AtomicCell<T, AtomicUnit>

Source

pub fn take(&self) -> T

Takes the value of the atomic cell, leaving Default::default() in its place.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(5);

assert_eq!(a.take(), 5);
assert_eq!(a.into_inner(), 0);
Source§

impl<T: Copy> AtomicCell<T, AtomicUnit>

Source

pub fn load(&self) -> T

Load a value from the the atomic cell.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.load(), 7);
Source

pub fn compare_update<C, const WEAK: bool>( &self, updater: C, ) -> Result<C::Final, C::Error>
where C: CompareUpdate<T, T>,

Tries to swap out the value in the cell for one provided by CompareUpdate.

First, updater.initial() is called, and the returned value is attempted to be exchanged into the cell. If it fails for any reason (e.g. it has been changed from other threads in the meantime), CompareUpdate::retry will be called to enable updates to the to-be-stored value between attempts. retry may return Err(_) to signal that the update attempt should be aborted.

When the attempt to store eventually succeeds, CompareUpdate::finalize will be called and the result returned.

The Current type is T. There are no special restrictions on the values returned by CompareUpdate::initial. The value passed to CompareUpdate::retry is the most recently read value from the cell.

Source

pub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>( &self, f: F, ) -> Result<T, T>

Fetches the value, and applies a function to it that returns an optional new value. Returns a Result of Ok(previous_value) if the function returned Some(_), else Err(previous_value).

Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns Some(_), but the function will have been applied only once to the stored value.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(7);

assert_eq!(a.fetch_update::<_, true>(|_| None), Err(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(7));
assert_eq!(a.fetch_update::<_, true>(|a| Some(a + 1)), Ok(8));
assert_eq!(a.load(), 9);
Source§

impl<T: Copy + PartialEq> AtomicCell<T, AtomicUnit>

Source

pub fn compare_exchange<const WEAK: bool>( &self, current: T, new: T, ) -> Result<T, T>

If the current value equals current, stores new into the atomic cell.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

§Examples
use atomic_cell::macros::AtomicCell;
use std::sync::atomic::AtomicU32;

let a = AtomicCell::<_, AtomicU32>::new(1);

assert_eq!(a.compare_exchange::<true>(2, 3), Err(1));
assert_eq!(a.load(), 1);

assert_eq!(a.compare_exchange::<true>(1, 2), Ok(1));
assert_eq!(a.load(), 2);
Source§

impl<T, A: AtomicStorage> AtomicCell<T, A>

Source

pub const SUPPORTED: bool = TransmuteUnderlying<T, A>::SIZE_MATCHES

true if the storage can support storing T.

Source

pub const ASSERT_SUPPORTED: ()

Tries to panic at compile-time if !SUPPORTED

Source

pub const REF_SUPPORTED: bool

true if the refences to A::Underlying is properly aligned with T, such that reference can be transmuted.

Source

pub const ASSERT_REF_SUPPORTED: ()

Tries to panic at compile-time if !REF_SUPPORTED

Trait Implementations§

Source§

impl<T: Copy + Debug> Debug for AtomicCell<T, AtomicBool>

Source§

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

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

impl<T: Copy + Debug> Debug for AtomicCell<T, AtomicI16>

Source§

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

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

impl<T: Copy + Debug> Debug for AtomicCell<T, AtomicI32>

Source§

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

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

impl<T: Copy + Debug> Debug for AtomicCell<T, AtomicI64>

Source§

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

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

impl<T: Copy + Debug> Debug for AtomicCell<T, AtomicI8>

Source§

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

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

impl<T: Copy + Debug> Debug for AtomicCell<T, AtomicIsize>

Source§

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

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

impl<P, T: Copy + Debug> Debug for AtomicCell<T, AtomicPtr<P>>

Source§

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

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

impl<T: Copy + Debug> Debug for AtomicCell<T, AtomicU16>

Source§

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

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

impl<T: Copy + Debug> Debug for AtomicCell<T, AtomicU32>

Source§

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

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

impl<T: Copy + Debug> Debug for AtomicCell<T, AtomicU64>

Source§

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

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

impl<T: Copy + Debug> Debug for AtomicCell<T, AtomicU8>

Source§

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

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

impl<T: Copy + Debug> Debug for AtomicCell<T, AtomicUnit>

Source§

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

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

impl<T: Copy + Debug> Debug for AtomicCell<T, AtomicUsize>

Source§

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

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

impl<T, A: AtomicStorage> Drop for AtomicCell<T, A>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl<T: Send, A: AtomicStorage> Send for AtomicCell<T, A>

Source§

impl<T: Send, A: AtomicStorage> Sync for AtomicCell<T, A>

Auto Trait Implementations§

§

impl<T, A> Freeze for AtomicCell<T, A>
where A: Freeze,

§

impl<T, A> RefUnwindSafe for AtomicCell<T, A>

§

impl<T, A> Unpin for AtomicCell<T, A>
where A: Unpin, T: Unpin,

§

impl<T, A> UnwindSafe for AtomicCell<T, A>
where A: UnwindSafe, T: UnwindSafe,

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<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<U, A> FromInner<A> for U
where A: AtomicStorage<Underlying = U>,

Source§

fn from_inner(a: A) -> U

Consumes the atomic and returns the contained value. Read more
Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

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

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
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.