use std::marker::PhantomData;
use std::ops::Deref;
use std::ptr::NonNull;
use std::sync::{Arc, Mutex};
use anyhow::{bail, Result};
use crate::collections::list::iterator::Iter;
use crate::collections::list::raw::{RawIter, RawList, RawNode};
use crate::collections::list::reference::Ref;
use crate::rcu::default::RcuDefaultFlavor;
use crate::rcu::flavor::RcuFlavor;
use crate::rcu::guard::RcuGuard;
use crate::utility::*;
pub struct RcuList<T, F = RcuDefaultFlavor> {
raw: RawList<T>,
mutex: Mutex<()>,
_unsend: PhantomUnsend<F>,
_unsync: PhantomUnsync<F>,
}
impl<T, F> RcuList<T, F>
where
F: RcuFlavor,
{
pub fn new() -> Arc<Self> {
let mut list = Arc::new(RcuList {
raw: unsafe { RawList::new() },
mutex: Default::default(),
_unsend: PhantomData,
_unsync: PhantomData,
});
unsafe { Arc::<Self>::get_mut(&mut list).unwrap().raw.init() };
list
}
pub fn contains<G>(&self, x: &T, guard: &G) -> bool
where
T: PartialEq,
G: RcuGuard<Flavor = F>,
{
self.iter_forward(guard).any(|item| item == x)
}
fn with_mutex<C, R>(&self, callback: C) -> Result<R>
where
C: FnOnce() -> R,
{
match self.mutex.lock() {
Err(_) => bail!("mutex of the list has been poisoned"),
Ok(guard) => {
let result = callback();
drop(guard);
Ok(result)
}
}
}
pub fn push_back(&self, data: T) -> Result<()> {
self.with_mutex(|| {
unsafe {
let node = RawNode::new(data);
self.raw.insert_back(node);
}
})
}
pub fn push_front(&self, data: T) -> Result<()> {
self.with_mutex(|| {
unsafe {
let node = RawNode::new(data);
self.raw.insert_front(node);
}
})
}
pub fn pop_back(&self) -> Result<Option<Ref<T, F>>>
where
T: Send,
{
self.with_mutex(|| {
let node = unsafe { self.raw.remove_back() };
NonNull::new(node).map(Ref::new)
})
}
pub fn pop_front(&self) -> Result<Option<Ref<T, F>>>
where
T: Send,
{
self.with_mutex(|| {
let node = unsafe { self.raw.remove_front() };
NonNull::new(node).map(Ref::new)
})
}
pub fn is_empty(&self) -> bool {
self.raw.empty()
}
pub fn back<'me, 'guard, G>(&'me self, guard: &'guard G) -> Option<&'guard T>
where
'me: 'guard,
G: RcuGuard<Flavor = F>,
{
let _ = guard;
unsafe { self.raw.get_back().as_ref() }.map(|r| r.deref())
}
pub fn front<'me, 'guard, G>(&'me self, guard: &'guard G) -> Option<&'guard T>
where
'me: 'guard,
G: RcuGuard<Flavor = F>,
{
let _ = guard;
unsafe { self.raw.get_front().as_ref() }.map(|r| r.deref())
}
pub fn iter_forward<'me, 'guard, G>(&'me self, guard: &'guard G) -> Iter<'guard, T, G, true>
where
'me: 'guard,
G: RcuGuard<Flavor = F>,
{
Iter::new(unsafe { RawIter::<T, true>::from_back(&self.raw) }, guard)
}
pub fn iter_reverse<'me, 'guard, G>(&'me self, guard: &'guard G) -> Iter<'guard, T, G, false>
where
'me: 'guard,
G: RcuGuard,
{
Iter::new(unsafe { RawIter::<T, false>::from_front(&self.raw) }, guard)
}
}
unsafe impl<T, F> Send for RcuList<T, F>
where
T: Send,
F: RcuFlavor,
{
}
unsafe impl<T, F> Sync for RcuList<T, F>
where
T: Sync,
F: RcuFlavor,
{
}
impl<T, F> Drop for RcuList<T, F> {
fn drop(&mut self) {
while let Some(mut ptr) = NonNull::new(unsafe { self.raw.remove_back() }) {
drop(unsafe { Box::from_raw(ptr.as_mut()) });
}
}
}