Expand description
§atomic_ptr_cell
Safe no_std repr(transparent) wrapper for AtomicPtr and &AtomicPtr with an api similar to a cell.
The crate requires an allocator using extern crate alloc; if used without std.
§Example using owned AtomicPtr:
use std::thread;
use atomic_ptr_cell::*;
static CELL: AtomicPointerCell<String> = AtomicPointerCell::new();
fn test() {
CELL.set("Hello".to_string());
let guard = CELL.borrow().unwrap();
assert_eq!("Hello", guard.as_str());
let jh = thread::spawn(|| {
CELL.set("World".to_string());
let guard = CELL.borrow().unwrap();
assert!("Hello" == guard.as_str() || "World" == guard.as_str());
drop(guard);
});
drop(guard);
//This small example already has a surprising amount of possible outcomes :D
let Some(value) = CELL.take() else {
_= jh.join();
let value = CELL.take().unwrap();
assert!("Hello" == value.as_str() || "World" == value.as_str());
return;
};
assert!("Hello" == value.as_str() || "World" == value.as_str());
_= jh.join();
if let Some(value2) = CELL.take() {
//Depending on the order of execution CELL.take() may return None here.
assert_ne!(value, value2);
}
}§Example using &AtomicPtr reference
use atomic_ptr_cell::*;
use std::ptr::null_mut;
use std::sync::atomic::AtomicPtr;
use std::thread;
static CELL: AtomicPtr<String> = AtomicPtr::new(null_mut());
fn test() {
// Safety: Caller must guarantee that the AtomicPtr never contains a non-null pointer that is not from Box::into_raw
let cell: AtomicPtrCell<String> = unsafe { AtomicPtrCell::new(&CELL) };
cell.set("Hello".to_string());
let guard = cell.borrow().unwrap();
assert_eq!("Hello", guard.as_str());
let jh = thread::spawn(move || {
//The AtomicPtrCell is copy as its layout is equivalent to &AtomicPtr
// making it easy to use in closures and threads.
// You just need to ensure the lifetime of &AtomicPtr outlives the scope.
// In this example the lifetime is static.
cell.set("World".to_string());
let guard = cell.borrow().unwrap();
assert!("Hello" == guard.as_str() || "World" == guard.as_str());
drop(guard);
});
drop(guard);
//This small example already has a surprising amount of possible outcomes :D
let Some(value) = cell.take() else {
_ = jh.join();
let value = cell.take().unwrap();
assert!("Hello" == value.as_str() || "World" == value.as_str());
return;
};
assert!("Hello" == value.as_str() || "World" == value.as_str());
_ = jh.join();
if let Some(value2) = cell.take() {
//Depending on the order of execution CELL.take() may return None here.
assert_ne!(value, value2);
}
}Structs§
- Atomic
Pointer Cell - This is a helper struct that is guaranteed to have the exact same layout as
AtomicPtr<T>. - Atomic
PtrCell - This is a helper struct that is guaranteed to have the exact same layout as
&AtomicPtr<T>. - Borrow
Guard - Borrow guard of a
AtomicCell. Once this cell is dropped the value is moved back into the cell if the cell is empty at that time.
Enums§
- Borrow
Swap Result - Result enum to indicate the outcomes of a
borrow_swapoperation. - Present
Result