use std::marker::PhantomData;
use std::ops::Deref;
use std::ptr::NonNull;
use std::sync::Arc;
use crate::collections::stack::iterator::{Iter, IterRef};
use crate::collections::stack::raw::{RawNode, RawStack};
use crate::collections::stack::reference::Ref;
use crate::rcu::default::RcuDefaultFlavor;
use crate::rcu::flavor::RcuFlavor;
use crate::rcu::guard::RcuGuard;
use crate::utility::*;
pub struct RcuStack<T, F = RcuDefaultFlavor> {
raw: RawStack<T>,
_unsend: PhantomUnsend<(T, F)>,
_unsync: PhantomUnsync<(T, F)>,
}
impl<T, F> RcuStack<T, F>
where
F: RcuFlavor,
{
pub fn new() -> Arc<Self> {
Arc::new(RcuStack {
raw: unsafe { RawStack::new() },
_unsend: PhantomData,
_unsync: PhantomData,
})
}
pub fn push(&self, data: T) {
let node = RawNode::new(data);
self.raw.push(node);
}
pub fn pop<G>(&self, guard: &G) -> Option<Ref<T, F>>
where
T: Send,
G: RcuGuard<Flavor = F>,
{
let _ = guard;
let node = unsafe { self.raw.pop() };
NonNull::new(node).map(Ref::new)
}
pub fn pop_all<G>(&self, _guard: &G) -> IterRef<T, F>
where
T: Send,
G: RcuGuard<Flavor = F>,
{
IterRef::new(unsafe { self.raw.pop_all() })
}
pub fn peek<'me, 'guard, G>(&'me self, _guard: &'guard G) -> Option<&'guard T>
where
'me: 'guard,
G: RcuGuard<Flavor = F>,
{
let node = unsafe { self.raw.head() };
unsafe { node.as_ref() }.map(|node| node.deref())
}
pub fn iter<'me, 'guard, G>(&'me self, guard: &'guard G) -> Iter<'guard, T, G>
where
'me: 'guard,
G: RcuGuard<Flavor = F>,
{
Iter::new(unsafe { self.raw.iter() }, guard)
}
pub fn is_empty(&self) -> bool {
self.raw.empty()
}
}
unsafe impl<T, F> Send for RcuStack<T, F>
where
T: Send,
F: RcuFlavor,
{
}
unsafe impl<T, F> Sync for RcuStack<T, F>
where
T: Sync,
F: RcuFlavor,
{
}
impl<T, F> Drop for RcuStack<T, F> {
fn drop(&mut self) {
let mut iter = unsafe { self.raw.pop_all() };
while let Some(ptr) = unsafe { iter.next().as_mut() } {
drop(unsafe { Box::from_raw(ptr) });
}
}
}