use std::marker::PhantomData;
use std::ops::Deref;
use container_of::container_of;
use urcu_cds_sys::list;
use crate::utility::*;
pub struct RawNode<T> {
handle: list::Head,
data: T,
}
impl<T> RawNode<T> {
pub fn new(data: T) -> Box<Self> {
Box::new(Self {
handle: Default::default(),
data,
})
}
fn into_handle(self: Box<Self>) -> *mut list::Head {
let node_ptr = Box::into_raw(self);
let node = unsafe { node_ptr.as_mut_unchecked() };
&mut node.handle
}
}
impl<T> Deref for RawNode<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
unsafe impl<T: Send> Send for RawNode<T> {}
unsafe impl<T: Sync> Sync for RawNode<T> {}
pub struct RawList<T> {
back: list::Head,
front: list::Head,
_unsend: PhantomUnsend<T>,
_unsync: PhantomUnsync<T>,
}
impl<T> RawList<T> {
pub unsafe fn new() -> Self {
Self {
back: Default::default(),
front: Default::default(),
_unsend: PhantomData,
_unsync: PhantomData,
}
}
pub unsafe fn init(&mut self) {
self.back.next = &mut self.front;
self.front.prev = &mut self.back;
}
pub unsafe fn insert_back(&self, node: Box<RawNode<T>>) {
let back = &self.back as *const list::Head as *mut list::Head;
unsafe { list::add_rcu(node.into_handle(), back) }
}
pub unsafe fn insert_front(&self, node: Box<RawNode<T>>) {
let front = &self.front as *const list::Head as *mut list::Head;
unsafe { list::add_tail_rcu(node.into_handle(), front) }
}
pub unsafe fn remove_back(&self) -> *mut RawNode<T> {
let handle = self.back.next;
if handle as *const list::Head != &self.front {
unsafe { list::del_rcu(handle) };
container_of!(handle, RawNode<T>, handle)
} else {
std::ptr::null_mut()
}
}
pub unsafe fn remove_front(&self) -> *mut RawNode<T> {
let handle = self.front.prev;
if handle as *const list::Head != &self.back {
unsafe { list::del_rcu(handle) };
container_of!(handle, RawNode<T>, handle)
} else {
std::ptr::null_mut()
}
}
pub unsafe fn get_back(&self) -> *const RawNode<T> {
let handle = self.back.next as *const list::Head;
if handle != &self.front {
container_of!(handle, RawNode<T>, handle)
} else {
std::ptr::null_mut()
}
}
pub unsafe fn get_front(&self) -> *const RawNode<T> {
let handle = self.front.prev as *const list::Head;
if handle != &self.back {
container_of!(handle, RawNode<T>, handle)
} else {
std::ptr::null_mut()
}
}
pub fn empty(&self) -> bool {
self.back.next as *const list::Head == &self.front
}
}
pub struct RawIter<T, const FORWARD: bool> {
current: *const list::Head,
last: *const list::Head,
_unsend: PhantomUnsend<T>,
_unsync: PhantomUnsync<T>,
}
impl<T> RawIter<T, true> {
pub unsafe fn from_back(list: &RawList<T>) -> Self {
Self {
current: crate::rcu::dereference(list.back.next),
last: &list.front,
_unsend: PhantomData,
_unsync: PhantomData,
}
}
}
impl<T> RawIter<T, false> {
pub unsafe fn from_front(list: &RawList<T>) -> Self {
Self {
current: crate::rcu::dereference(list.front.prev),
last: &list.back,
_unsend: PhantomData,
_unsync: PhantomData,
}
}
}
impl<T, const FORWARD: bool> RawIter<T, FORWARD> {
pub unsafe fn next(&mut self) -> *const RawNode<T> {
if self.current == self.last {
return std::ptr::null();
}
match self.current.as_ref() {
None => std::ptr::null(),
Some(handle) => {
self.current = if FORWARD {
crate::rcu::dereference_mut(handle.next)
} else {
crate::rcu::dereference_mut(handle.prev)
};
container_of!(handle as *const list::Head, RawNode<T>, handle)
}
}
}
}