use crate::sync::atomic;
use std::fmt::Debug;
pub struct Record<T> {
pub ptr: atomic::AtomicPtr<T>,
pub next: atomic::AtomicPtr<Record<T>>,
}
impl<T> Record<T> {
pub fn boxed_empty() -> Box<Self> {
Box::new(Self {
ptr: atomic::AtomicPtr::new(std::ptr::null_mut()),
next: atomic::AtomicPtr::new(std::ptr::null_mut()),
})
}
pub fn load_next(&self, order: atomic::Ordering) -> Option<&Self> {
let ptr = self.next.load(order);
if ptr.is_null() {
return None;
}
Some(unsafe { &*ptr })
}
pub fn reset(&self) {
self.ptr
.store(std::ptr::null_mut(), atomic::Ordering::SeqCst);
}
}
impl<T> Debug for Record<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let ptr = self.ptr.load(atomic::Ordering::SeqCst);
let next = self.next.load(atomic::Ordering::SeqCst);
write!(f, "Record ( ptr = {:p}, next = {:p} )", ptr, next)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn store_load_next() {
let record = Record::<u32>::boxed_empty();
let next_record_ptr = Box::into_raw(Record::boxed_empty());
assert_eq!(true, record.load_next(atomic::Ordering::SeqCst).is_none());
record.next.store(next_record_ptr, atomic::Ordering::SeqCst);
let next_result = record.load_next(atomic::Ordering::SeqCst);
assert_eq!(true, next_result.is_some());
{
unsafe { Box::from_raw(next_record_ptr) };
}
}
}