use std::marker::PhantomData;
use std::ptr::NonNull;
use std::sync::Arc;
use crate::collections::queue::raw::{RawNode, RawQueue};
use crate::collections::queue::reference::Ref;
use crate::rcu::default::RcuDefaultFlavor;
use crate::rcu::flavor::RcuFlavor;
use crate::rcu::guard::RcuGuard;
use crate::utility::*;
pub struct RcuQueue<T, F = RcuDefaultFlavor> {
raw: RawQueue<T, F>,
_unsend: PhantomUnsend,
_unsync: PhantomUnsync,
}
impl<T, F> RcuQueue<T, F>
where
F: RcuFlavor,
{
pub fn new() -> Arc<Self> {
let mut queue = Arc::new(RcuQueue {
raw: unsafe { RawQueue::new() },
_unsend: PhantomData,
_unsync: PhantomData,
});
unsafe { Arc::<Self>::get_mut(&mut queue).unwrap().raw.init() };
queue
}
pub fn push<G>(&self, data: T, _guard: &G)
where
T: Send,
G: RcuGuard<Flavor = F>,
{
let node = RawNode::new(data);
unsafe { self.raw.enqueue(node) };
}
pub fn pop<G>(&self, _guard: &G) -> Option<Ref<T, F>>
where
T: Send,
G: RcuGuard<Flavor = F>,
{
NonNull::new(unsafe { self.raw.dequeue() }).map(Ref::<T, F>::new)
}
}
unsafe impl<T, F> Send for RcuQueue<T, F>
where
T: Send,
F: RcuFlavor,
{
}
unsafe impl<T, F> Sync for RcuQueue<T, F>
where
T: Sync,
F: RcuFlavor,
{
}
impl<T, F> Drop for RcuQueue<T, F> {
fn drop(&mut self) {
for ptr in unsafe { self.raw.dequeue_all() } {
drop(unsafe { Box::from_raw(ptr) });
}
}
}