use std::marker::{PhantomData, PhantomPinned}; use std::pin::Pin; use std::ptr::NonNull; use crossbeam::atomic::AtomicCell; use crate::alloc::Ptr; pub struct List> + ?Sized> { // TODO they should be in one cell prev: AtomicCell>>>, next: AtomicCell>>, _pinned: PhantomPinned, } impl> + ?Sized> Default for List { fn default() -> List { List { prev: AtomicCell::default(), next: AtomicCell::default(), _pinned: PhantomPinned, } } } impl> + ?Sized> List { pub fn insert(self: Pin<&Self>, new: Pin<&T>) { let this: &Self = &*self; let new: &T = &*new; let list: &List = new.as_ref(); list.prev.store(Some(Ptr(NonNull::from(this)))); list.next.store(this.next.load()); if let Some(next) = this.next.load() { unsafe { let next: &List = next.as_ref().as_ref(); next.prev.store(Some(Ptr(NonNull::from(list)))); } } this.next.store(Some(Ptr(NonNull::from(new)))); } pub fn is_head(&self) -> bool { self.prev.load().is_none() } } impl> + ?Sized> Drop for List { fn drop(&mut self) { if let Some(prev) = self.prev.load() { unsafe { prev.as_ref().next.store(self.next.load()); } } if let Some(next) = self.next.load() { unsafe { next.as_ref().as_ref().prev.store(self.prev.load()); } } } } impl<'a, T: AsRef> + ?Sized> IntoIterator for Pin<&'a List> { type IntoIter = Iter<'a, T>; type Item = Pin<&'a T>; fn into_iter(self) -> Iter<'a, T> { Iter { next: (*self).next.load(), _marker: PhantomData, } } } pub struct Iter<'a, T: AsRef> + ?Sized + 'a> { next: Option>, _marker: PhantomData<&'a T>, } impl<'a, T: AsRef> + ?Sized> Iterator for Iter<'a, T> { type Item = Pin<&'a T>; fn next(&mut self) -> Option> { if let Some(next) = self.next { unsafe { self.next = next.as_ref().as_ref().next.load(); Some(Pin::new_unchecked(&*next.as_ptr())) } } else { None } } }