pub struct PtrCell<T> { /* private fields */ }
Expand description
Thread-safe cell based on atomic pointers
This type stores its data externally by leaking it with Box
. Synchronization is achieved
by atomically manipulating pointers to the data
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
let cell: PtrCell<u16> = 0x81D.into();
assert_eq!(cell.replace(Some(2047), Relaxed), Some(0x81D));
assert_eq!(cell.is_empty(Relaxed), false);
assert_eq!(cell.take(Relaxed), Some(2047))
§Pointer Safety
When dereferencing a pointer to the cell’s value, you must ensure that the pointed-to memory
hasn’t been reclaimed. For example, replace
and its
derivatives (set
and take
) automatically reclaim memory. Be
careful not to miss any calls to such functions made from other threads
This also applies to externally-sourced pointers, like the ptr
parameter in
from_ptr
Implementations§
Source§impl<T> PtrCell<T>
impl<T> PtrCell<T>
Sourcepub fn map_owner<F>(&self, new: F, order: Semantics)
pub fn map_owner<F>(&self, new: F, order: Semantics)
Inserts the value constructed from this cell by new
into the cell itself
Think of this like the push
method of a linked list, where each node contains a PtrCell
§Examples
The code below turns a sentence into a naive linked list of words, which is then assembled
back into a String
use ptr_cell::{PtrCell, Semantics};
struct Node<T> {
pub value: T,
pub next: PtrCell<Self>,
}
impl<T> AsMut<PtrCell<Self>> for Node<T> {
fn as_mut(&mut self) -> &mut ptr_cell::PtrCell<Self> {
&mut self.next
}
}
let cell = PtrCell::default();
for value in "Hachó en México".split_whitespace().rev() {
cell.map_owner(|next| Node { value, next }, Semantics::Relaxed);
}
let Node { value, mut next } = cell
.take(Semantics::Relaxed)
.expect("Some values should've been inserted into the cell");
let mut decoded = value.to_string();
while let Some(node) = next.take(Semantics::Relaxed) {
decoded.extend([" ", node.value]);
next = node.next
}
assert_eq!(decoded, "Hachó en México")
Sourcepub fn swap(&self, other: &mut Self, order: Semantics)
pub fn swap(&self, other: &mut Self, order: Semantics)
Swaps the values of two cells
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
let one: PtrCell<u8> = 1.into();
let mut two: PtrCell<u8> = 2.into();
one.swap(&mut two, Relaxed);
assert_eq!(two.take(Relaxed), Some(1));
assert_eq!(one.take(Relaxed), Some(2))
Sourcepub fn take(&self, order: Semantics) -> Option<T>
pub fn take(&self, order: Semantics) -> Option<T>
Takes out the cell’s value
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
let cell: PtrCell<u8> = 45.into();
assert_eq!(cell.take(Relaxed), Some(45));
assert_eq!(cell.take(Relaxed), None)
Sourcepub fn take_ptr(&self, order: Semantics) -> *mut T
pub fn take_ptr(&self, order: Semantics) -> *mut T
Takes out the cell’s pointer
§Safety
Not inherently unsafe. See Pointer Safety
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
let cell: PtrCell<u8> = 45.into();
let ptr = cell.take_ptr(Relaxed);
assert_eq!(unsafe { ptr_cell::PtrCell::heap_reclaim(ptr) }, Some(45));
assert_eq!(cell.take_ptr(Relaxed), std::ptr::null_mut())
Sourcepub fn set(&self, slot: Option<T>, order: Semantics)
pub fn set(&self, slot: Option<T>, order: Semantics)
Inserts a value into the cell
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
let cell = PtrCell::default();
cell.set(Some(1776), Relaxed);
assert_eq!(cell.take(Relaxed), Some(1776))
Sourcepub unsafe fn set_ptr(&self, ptr: *mut T, order: Semantics)
pub unsafe fn set_ptr(&self, ptr: *mut T, order: Semantics)
Inserts a pointer into the cell
§Safety
The pointed-to memory must conform to the memory layout used by Box
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
let cell = PtrCell::default();
let ptr = PtrCell::heap_leak(Some(1776));
unsafe { cell.set_ptr(ptr, Relaxed) };
assert_eq!(cell.take(Relaxed), Some(1776))
Sourcepub fn replace(&self, slot: Option<T>, order: Semantics) -> Option<T>
pub fn replace(&self, slot: Option<T>, order: Semantics) -> Option<T>
Replaces the cell’s value
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
let cell = PtrCell::from('a');
assert_eq!(cell.replace(Some('b'), Relaxed), Some('a'));
assert_eq!(cell.take(Relaxed), Some('b'))
Sourcepub fn replace_ptr(&self, ptr: *mut T, order: Semantics) -> *mut T
pub fn replace_ptr(&self, ptr: *mut T, order: Semantics) -> *mut T
Replaces the cell’s pointer
WARNING: THIS FUNCTION WAS ERRONEOUSLY LEFT SAFE. IT’S UNSAFE AND WILL BE MARKED AS SUCH IN THE NEXT MAJOR RELEASE
§Safety
The pointed-to memory must conform to the memory layout used by Box
See also: Pointer Safety
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
unsafe {
let a = PtrCell::heap_leak(Some('a'));
let b = PtrCell::heap_leak(Some('b'));
let cell = PtrCell::from_ptr(a);
assert_eq!(cell.replace_ptr(b, Relaxed), a);
assert_eq!(cell.take_ptr(Relaxed), b);
PtrCell::heap_reclaim(a);
PtrCell::heap_reclaim(b);
}
Sourcepub fn get_mut(&mut self) -> Option<&mut T>
pub fn get_mut(&mut self) -> Option<&mut T>
Mutably borrows the cell’s value
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
let mut text = PtrCell::from("Point".to_string());
text.get_mut()
.expect("The cell should contain a value")
.push_str("er");
assert_eq!(text.take(Relaxed), Some("Pointer".to_string()))
Sourcepub fn get_ptr(&self, order: Semantics) -> *mut T
pub fn get_ptr(&self, order: Semantics) -> *mut T
Returns a pointer to the cell’s value
§Safety
Not inherently unsafe. See Pointer Safety
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
let cell = PtrCell::<[u8; 3]>::default();
assert_eq!(cell.get_ptr(Relaxed), std::ptr::null_mut())
Sourcepub fn is_empty(&self, order: Semantics) -> bool
pub fn is_empty(&self, order: Semantics) -> bool
Determines whether this cell is empty
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
let cell = PtrCell::<[u8; 3]>::default();
assert!(cell.is_empty(Relaxed))
Sourcepub fn new(slot: Option<T>) -> Self
pub fn new(slot: Option<T>) -> Self
Constructs a cell
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
let cell = PtrCell::new(Some(0xFAA));
assert_eq!(cell.take(Relaxed), Some(0xFAA));
assert!(cell.is_empty(Relaxed))
Sourcepub const unsafe fn from_ptr(ptr: *mut T) -> Self
pub const unsafe fn from_ptr(ptr: *mut T) -> Self
Constructs a cell that owns leaked memory
A null pointer represents None
§Safety
The memory must conform to the memory layout used by Box
§Usage
use ptr_cell::{PtrCell, Semantics::Relaxed};
let ptr = PtrCell::heap_leak(Some(0xFAA));
let cell = unsafe { PtrCell::from_ptr(ptr) };
assert_eq!(cell.take(Relaxed), Some(0xFAA));
assert!(cell.is_empty(Relaxed))
Sourcepub unsafe fn heap_reclaim(ptr: *mut T) -> Option<T>
pub unsafe fn heap_reclaim(ptr: *mut T) -> Option<T>
Reclaims ownership of leaked memory
A null pointer represents None
§Safety
The memory must conform to the memory layout used by Box
Dereferencing ptr
after this function has been called may cause undefined behavior
§Usage
use ptr_cell::PtrCell;
let ptr = PtrCell::heap_leak(Some(1155));
assert_eq!(unsafe { PtrCell::heap_reclaim(ptr) }, Some(1155))
Sourcepub fn heap_leak(slot: Option<T>) -> *mut T
pub fn heap_leak(slot: Option<T>) -> *mut T
Leaks a value to the heap
None
is represented by a null pointer
The memory will conform to the memory layout used by Box
§Usage
use ptr_cell::PtrCell;
let ptr = PtrCell::heap_leak(Some(1155));
assert_eq!(unsafe { PtrCell::heap_reclaim(ptr) }, Some(1155))