Struct atomic_cell::macros::AtomicCell
source · [−]#[repr(transparent)]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 AtomicCell
s 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
sourceimpl<T, A: AtomicStorage> AtomicCell<UnderlyingMarker<T>, StorageMarker<A>>
impl<T, A: AtomicStorage> AtomicCell<UnderlyingMarker<T>, StorageMarker<A>>
sourcepub fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> A::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, A::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: A::Underlying,
new: T
) -> Result<T, (T, A::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<A::Underlying, T>,
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);
sourceimpl<T: Default, A: AtomicStorage> AtomicCell<UnderlyingMarker<T>, StorageMarker<A>>
impl<T: Default, A: AtomicStorage> AtomicCell<UnderlyingMarker<T>, StorageMarker<A>>
sourceimpl<T: Copy, A: AtomicStorage> AtomicCell<UnderlyingMarker<T>, StorageMarker<A>>
impl<T: Copy, A: AtomicStorage> AtomicCell<UnderlyingMarker<T>, StorageMarker<A>>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq, A: AtomicStorage> AtomicCell<UnderlyingMarker<T>, StorageMarker<A>>
impl<T: Copy + PartialEq, A: AtomicStorage> AtomicCell<UnderlyingMarker<T>, StorageMarker<A>>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<P, T> AtomicCell<T, AtomicPtr<P>>
impl<P, T> AtomicCell<T, AtomicPtr<P>>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicPtr<P> as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicPtr<P> as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicPtr<P> as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicPtr<P> as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicPtr<P> as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicPtr<P> as AtomicStorageBase>::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);
sourceimpl<P, T: Default> AtomicCell<T, AtomicPtr<P>>
impl<P, T: Default> AtomicCell<T, AtomicPtr<P>>
sourceimpl<P, T: Copy> AtomicCell<T, AtomicPtr<P>>
impl<P, T: Copy> AtomicCell<T, AtomicPtr<P>>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<P, T: Copy + PartialEq> AtomicCell<T, AtomicPtr<P>>
impl<P, T: Copy + PartialEq> AtomicCell<T, AtomicPtr<P>>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T> AtomicCell<T, AtomicUsize>
impl<T> AtomicCell<T, AtomicUsize>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicUsize as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicUsize as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicUsize as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicUsize as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicUsize as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicUsize as AtomicStorageBase>::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);
sourceimpl<T: Default> AtomicCell<T, AtomicUsize>
impl<T: Default> AtomicCell<T, AtomicUsize>
sourceimpl<T: Copy> AtomicCell<T, AtomicUsize>
impl<T: Copy> AtomicCell<T, AtomicUsize>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq> AtomicCell<T, AtomicUsize>
impl<T: Copy + PartialEq> AtomicCell<T, AtomicUsize>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T> AtomicCell<T, AtomicIsize>
impl<T> AtomicCell<T, AtomicIsize>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicIsize as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicIsize as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicIsize as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicIsize as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicIsize as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicIsize as AtomicStorageBase>::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);
sourceimpl<T: Default> AtomicCell<T, AtomicIsize>
impl<T: Default> AtomicCell<T, AtomicIsize>
sourceimpl<T: Copy> AtomicCell<T, AtomicIsize>
impl<T: Copy> AtomicCell<T, AtomicIsize>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq> AtomicCell<T, AtomicIsize>
impl<T: Copy + PartialEq> AtomicCell<T, AtomicIsize>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T> AtomicCell<T, AtomicU64>
impl<T> AtomicCell<T, AtomicU64>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicU64 as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicU64 as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicU64 as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicU64 as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicU64 as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicU64 as AtomicStorageBase>::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);
sourceimpl<T: Default> AtomicCell<T, AtomicU64>
impl<T: Default> AtomicCell<T, AtomicU64>
sourceimpl<T: Copy> AtomicCell<T, AtomicU64>
impl<T: Copy> AtomicCell<T, AtomicU64>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq> AtomicCell<T, AtomicU64>
impl<T: Copy + PartialEq> AtomicCell<T, AtomicU64>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T> AtomicCell<T, AtomicI64>
impl<T> AtomicCell<T, AtomicI64>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicI64 as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicI64 as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicI64 as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicI64 as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicI64 as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicI64 as AtomicStorageBase>::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);
sourceimpl<T: Default> AtomicCell<T, AtomicI64>
impl<T: Default> AtomicCell<T, AtomicI64>
sourceimpl<T: Copy> AtomicCell<T, AtomicI64>
impl<T: Copy> AtomicCell<T, AtomicI64>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq> AtomicCell<T, AtomicI64>
impl<T: Copy + PartialEq> AtomicCell<T, AtomicI64>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T> AtomicCell<T, AtomicU32>
impl<T> AtomicCell<T, AtomicU32>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicU32 as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicU32 as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicU32 as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicU32 as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicU32 as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicU32 as AtomicStorageBase>::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);
sourceimpl<T: Default> AtomicCell<T, AtomicU32>
impl<T: Default> AtomicCell<T, AtomicU32>
sourceimpl<T: Copy> AtomicCell<T, AtomicU32>
impl<T: Copy> AtomicCell<T, AtomicU32>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq> AtomicCell<T, AtomicU32>
impl<T: Copy + PartialEq> AtomicCell<T, AtomicU32>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T> AtomicCell<T, AtomicI32>
impl<T> AtomicCell<T, AtomicI32>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicI32 as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicI32 as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicI32 as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicI32 as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicI32 as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicI32 as AtomicStorageBase>::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);
sourceimpl<T: Default> AtomicCell<T, AtomicI32>
impl<T: Default> AtomicCell<T, AtomicI32>
sourceimpl<T: Copy> AtomicCell<T, AtomicI32>
impl<T: Copy> AtomicCell<T, AtomicI32>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq> AtomicCell<T, AtomicI32>
impl<T: Copy + PartialEq> AtomicCell<T, AtomicI32>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T> AtomicCell<T, AtomicU16>
impl<T> AtomicCell<T, AtomicU16>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicU16 as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicU16 as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicU16 as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicU16 as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicU16 as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicU16 as AtomicStorageBase>::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);
sourceimpl<T: Default> AtomicCell<T, AtomicU16>
impl<T: Default> AtomicCell<T, AtomicU16>
sourceimpl<T: Copy> AtomicCell<T, AtomicU16>
impl<T: Copy> AtomicCell<T, AtomicU16>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq> AtomicCell<T, AtomicU16>
impl<T: Copy + PartialEq> AtomicCell<T, AtomicU16>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T> AtomicCell<T, AtomicI16>
impl<T> AtomicCell<T, AtomicI16>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicI16 as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicI16 as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicI16 as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicI16 as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicI16 as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicI16 as AtomicStorageBase>::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);
sourceimpl<T: Default> AtomicCell<T, AtomicI16>
impl<T: Default> AtomicCell<T, AtomicI16>
sourceimpl<T: Copy> AtomicCell<T, AtomicI16>
impl<T: Copy> AtomicCell<T, AtomicI16>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq> AtomicCell<T, AtomicI16>
impl<T: Copy + PartialEq> AtomicCell<T, AtomicI16>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T> AtomicCell<T, AtomicU8>
impl<T> AtomicCell<T, AtomicU8>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicU8 as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicU8 as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicU8 as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicU8 as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicU8 as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicU8 as AtomicStorageBase>::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);
sourceimpl<T: Default> AtomicCell<T, AtomicU8>
impl<T: Default> AtomicCell<T, AtomicU8>
sourceimpl<T: Copy> AtomicCell<T, AtomicU8>
impl<T: Copy> AtomicCell<T, AtomicU8>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq> AtomicCell<T, AtomicU8>
impl<T: Copy + PartialEq> AtomicCell<T, AtomicU8>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T> AtomicCell<T, AtomicI8>
impl<T> AtomicCell<T, AtomicI8>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicI8 as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicI8 as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicI8 as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicI8 as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicI8 as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicI8 as AtomicStorageBase>::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);
sourceimpl<T: Default> AtomicCell<T, AtomicI8>
impl<T: Default> AtomicCell<T, AtomicI8>
sourceimpl<T: Copy> AtomicCell<T, AtomicI8>
impl<T: Copy> AtomicCell<T, AtomicI8>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq> AtomicCell<T, AtomicI8>
impl<T: Copy + PartialEq> AtomicCell<T, AtomicI8>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T> AtomicCell<T, AtomicBool>
impl<T> AtomicCell<T, AtomicBool>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicBool as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicBool as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicBool as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicBool as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicBool as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicBool as AtomicStorageBase>::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);
sourceimpl<T: Default> AtomicCell<T, AtomicBool>
impl<T: Default> AtomicCell<T, AtomicBool>
sourceimpl<T: Copy> AtomicCell<T, AtomicBool>
impl<T: Copy> AtomicCell<T, AtomicBool>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq> AtomicCell<T, AtomicBool>
impl<T: Copy + PartialEq> AtomicCell<T, AtomicBool>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T> AtomicCell<T, AtomicUnit>
impl<T> AtomicCell<T, AtomicUnit>
sourcepub const fn new(val: T) -> Self
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);
sourcepub fn into_inner(self) -> T
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);
sourcepub fn get_mut(&mut self) -> &mut T
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));
sourcepub fn store(&self, val: T)
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);
sourcepub fn load_raw(&self) -> <AtomicUnit as AtomicStorageBase>::Underlying
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);
sourcepub fn swap(&self, val: T) -> T
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);
sourcepub fn get_raw(val: T) -> (T, <AtomicUnit as AtomicStorageBase>::Underlying)
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
);
sourcepub fn compare_exchange_raw<const WEAK: bool>(
&self,
current: <AtomicUnit as AtomicStorageBase>::Underlying,
new: T
) -> Result<T, (T, <AtomicUnit as AtomicStorageBase>::Underlying)>
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.
sourcepub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicUnit as AtomicStorageBase>::Underlying, T>,
pub fn compare_update_raw<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<<AtomicUnit as AtomicStorageBase>::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);
sourceimpl<T: Default> AtomicCell<T, AtomicUnit>
impl<T: Default> AtomicCell<T, AtomicUnit>
sourceimpl<T: Copy> AtomicCell<T, AtomicUnit>
impl<T: Copy> AtomicCell<T, AtomicUnit>
sourcepub fn load(&self) -> T
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);
sourcepub fn compare_update<C, const WEAK: bool>(
&self,
updater: C
) -> Result<C::Final, C::Error>where
C: CompareUpdate<T, T>,
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.
sourcepub fn fetch_update<F: FnMut(T) -> Option<T>, const WEAK: bool>(
&self,
f: F
) -> Result<T, T>
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);
sourceimpl<T: Copy + PartialEq> AtomicCell<T, AtomicUnit>
impl<T: Copy + PartialEq> AtomicCell<T, AtomicUnit>
sourcepub fn compare_exchange<const WEAK: bool>(
&self,
current: T,
new: T
) -> Result<T, T>
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);
sourceimpl<T, A: AtomicStorage> AtomicCell<T, A>
impl<T, A: AtomicStorage> AtomicCell<T, A>
sourcepub const SUPPORTED: bool = TransmuteUnderlying<T, A>::SIZE_MATCHES
pub const SUPPORTED: bool = TransmuteUnderlying<T, A>::SIZE_MATCHES
true
if the storage can support storing T
.
sourcepub const ASSERT_SUPPORTED: () = _
pub const ASSERT_SUPPORTED: () = _
Tries to panic at compile-time if !SUPPORTED
sourcepub const REF_SUPPORTED: bool = _
pub const REF_SUPPORTED: bool = _
true
if the refences to A::Underlying
is properly aligned with T
, such that reference can be transmuted.
sourcepub const ASSERT_REF_SUPPORTED: () = _
pub const ASSERT_REF_SUPPORTED: () = _
Tries to panic at compile-time if !REF_SUPPORTED