+#[cfg(test)]
+mod test;
+
use std::collections::HashSet;
use std::fmt::{self, Debug};
use std::marker::PhantomData;
Ok(())
}
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use fmt::Write as _;
-
- mod list {
- use super::*;
- use std::hint::unreachable_unchecked;
- use std::iter;
-
- #[derive(Debug)]
- pub struct Node<T> {
- back: Option<Ptr<Node<T>>>,
- next: Option<Ptr<Node<T>>>,
- pub data: T,
- }
-
- #[derive(Debug)]
- pub struct List<T: Debug> {
- head: Option<Ptr<Node<T>>>,
- tail: Option<Ptr<Node<T>>>,
- noalias: NoAliasSingleton,
- }
-
- #[derive(Debug, Eq, PartialEq)]
- pub enum HeadAndTail<T> {
- None,
- One(T),
- Both(T, T),
- }
-
- type P<T> = Ptr<Node<T>>;
-
- impl<T: Debug> List<T> {
- pub fn new() -> Self {
- let noalias = unsafe { NoAliasSingleton::init() };
- List { head: None, tail: None, noalias }
- }
-
- pub fn check_consistency(&self) {
- dbg!(self);
- let tok = self.noalias.ref_token();
- let mut last: Option<P<T>> = None;
- let mut node = self.head;
- while let Some(node_) = node {
- dbg!(node_);
- let node__ = node_.borrow(&tok);
- dbg!(node__);
- assert_eq!(last.as_ptr(), node__.back.as_ptr());
- last = Some(node_);
- node = node__.next;
- }
- assert_eq!(self.tail.as_ptr(), last.as_ptr());
- }
-
- pub fn append(&mut self, data: T) {
- let node = Node {
- back: self.head,
- next: None,
- data,
- };
- let node = Ptr::new_heap(node);
- if let Some(old_tail) = self.tail {
- old_tail.borrow_mut(&mut self.noalias).next = Some(node);
- } else {
- self.head = Some(node);
- };
- self.tail = Some(node);
- }
-
- pub fn front(&self) -> Option<&T> {
- let tok = self.noalias.ref_token();
- let head = self.head?;
- Some(&head.borrow(tok).data)
- }
-
- pub fn front_mut(&mut self) -> Option<&mut T> {
- let tok = self.noalias.mut_token();
- let head = self.head?;
- Some(&mut head.borrow_mut(tok).data)
- }
-
- pub fn pop_front(&mut self) -> Option<T> {
- let tok = self.noalias.mut_token();
- Self::pop_front_inner(
- tok,
- &mut self.head,
- &mut self.tail,
- )
- }
-
- pub fn head_and_tail_mut(&mut self) -> HeadAndTail<&mut T> {
- let Some(head) = self.head
- else { return HeadAndTail::None };
-
- let multi = self.noalias.mut_token().multi_static();
-
- let Ok(multi) = multi.borrow_mut(head)
- else { unsafe { unreachable_unchecked() } };
-
- let tail = unsafe { self.tail.unwrap_unchecked() };
-
- match multi.borrow_mut(tail) {
- Ok(y) => {
- let (((), head), tail) = y.finish();
- HeadAndTail::Both(&mut head.data, &mut tail.data)
- },
- Err(n) => {
- let ((), head) = n.finish();
- HeadAndTail::One(&mut head.data)
- }
- }
- }
-
- pub fn all(&self) -> impl Iterator<Item = &T> {
- let tok = self.noalias.ref_token();
- Self::iter_ptrs(self.head, move |node| {
- let node = node.borrow(tok);
- (&node.data, node.next)
- })
- }
-
- pub fn all_mut_safe(&mut self) -> impl Iterator<Item = &mut T> {
- let mut multi = self.noalias.multi_runtime();
- Self::iter_ptrs(self.head, move |node| {
- let node = multi.borrow_mut(node).expect("untangled!");
- (&mut node.data, node.next)
- })
- }
-
- pub fn all_mut_fast(&mut self) -> impl Iterator<Item = &mut T> {
- Self::iter_ptrs(self.head, |node| {
- let tok = unsafe { MutToken::new_unchecked() };
- let node = node.borrow_mut(tok);
- (&mut node.data, node.next)
- })
- }
-
- // We wouldn't do this, since it's daft, but
- // it lets us demonstrate passing a token.
- fn pop_front_inner<'a>(
- mut tok: MutToken<'a>,
- head: &mut Option<P<T>>,
- tail: &mut Option<P<T>>,
- ) -> Option<T> {
- let deleting = (*head)?;
- let new_head = deleting.borrow(&tok).next;
- *head = new_head;
- if let Some(new_head) = new_head {
- new_head.borrow_mut(&mut tok).back = None;
- } else {
- *tail = None;
- }
- let deleted = unsafe { deleting.free_heap(&mut tok) };
- Some(deleted.data)
- }
-
- fn iter_ptrs<'i, I: 'i>(
- head: Option<P<T>>,
- mut node_map: impl FnMut(P<T>) -> (I, Option<P<T>>) + 'i,
- ) -> impl Iterator<Item = I> + 'i
- where T: 'i
- {
- let mut next = head;
- iter::from_fn(move || {
- let node = next?;
- let item;
- (item, next) = node_map(node);
- Some(item)
- })
- }
- }
-
- impl<T: Debug> Drop for List<T> {
- fn drop(&mut self) {
- while let Some(_) = Self::pop_front_inner(
- self.noalias.mut_token(),
- &mut self.head,
- &mut self.tail,
- ) { }
- }
- }
- }
-
- #[test]
- fn demo() {
- use list::{List, HeadAndTail};
- use HeadAndTail as H;
-
- let s = |s: &str| format!("{s}");
-
- let l = List::<String>::new();
- l.check_consistency();
- assert_eq!(l.front(), None);
- drop(l);
-
- let mut l = List::new(); l.check_consistency();
- assert_eq!(l.head_and_tail_mut(), H::None);
-
- l.append(s("hi")); l.check_consistency();
- assert_eq!(l.head_and_tail_mut(), H::One(&mut s("hi")));
-
- l.append(s("ho")); l.check_consistency();
- assert_eq!(l.head_and_tail_mut(), H::Both(&mut s("hi"), &mut s("ho")));
-
- write!(l.front_mut().unwrap(), "!").unwrap();
- assert_eq!(l.pop_front(), Some(s("hi!"))); l.check_consistency();
- assert_eq!(l.front(), Some(&s("ho"))); l.check_consistency();
-
- drop(l);
- }
-}
-
-
-
--- /dev/null
+use super::*;
+use std::hint::unreachable_unchecked;
+use std::iter;
+
+#[derive(Debug)]
+pub struct Node<T> {
+ back: Option<Ptr<Node<T>>>,
+ next: Option<Ptr<Node<T>>>,
+ pub data: T,
+}
+
+#[derive(Debug)]
+pub struct List<T: Debug> {
+ head: Option<Ptr<Node<T>>>,
+ tail: Option<Ptr<Node<T>>>,
+ noalias: NoAliasSingleton,
+}
+
+#[derive(Debug, Eq, PartialEq)]
+pub enum HeadAndTail<T> {
+ None,
+ One(T),
+ Both(T, T),
+}
+
+type P<T> = Ptr<Node<T>>;
+
+impl<T: Debug> List<T> {
+ pub fn new() -> Self {
+ let noalias = unsafe { NoAliasSingleton::init() };
+ List { head: None, tail: None, noalias }
+ }
+
+ pub fn check_consistency(&self) {
+ dbg!(self);
+ let tok = self.noalias.ref_token();
+ let mut last: Option<P<T>> = None;
+ let mut node = self.head;
+ while let Some(node_) = node {
+ dbg!(node_);
+ let node__ = node_.borrow(&tok);
+ dbg!(node__);
+ assert_eq!(last.as_ptr(), node__.back.as_ptr());
+ last = Some(node_);
+ node = node__.next;
+ }
+ assert_eq!(self.tail.as_ptr(), last.as_ptr());
+ }
+
+ pub fn append(&mut self, data: T) {
+ let node = Node {
+ back: self.head,
+ next: None,
+ data,
+ };
+ let node = Ptr::new_heap(node);
+ if let Some(old_tail) = self.tail {
+ old_tail.borrow_mut(&mut self.noalias).next = Some(node);
+ } else {
+ self.head = Some(node);
+ };
+ self.tail = Some(node);
+ }
+
+ pub fn front(&self) -> Option<&T> {
+ let tok = self.noalias.ref_token();
+ let head = self.head?;
+ Some(&head.borrow(tok).data)
+ }
+
+ pub fn front_mut(&mut self) -> Option<&mut T> {
+ let tok = self.noalias.mut_token();
+ let head = self.head?;
+ Some(&mut head.borrow_mut(tok).data)
+ }
+
+ pub fn pop_front(&mut self) -> Option<T> {
+ let tok = self.noalias.mut_token();
+ Self::pop_front_inner(
+ tok,
+ &mut self.head,
+ &mut self.tail,
+ )
+ }
+
+ pub fn head_and_tail_mut(&mut self) -> HeadAndTail<&mut T> {
+ let Some(head) = self.head
+ else { return HeadAndTail::None };
+
+ let multi = self.noalias.mut_token().multi_static();
+
+ let Ok(multi) = multi.borrow_mut(head)
+ else { unsafe { unreachable_unchecked() } };
+
+ let tail = unsafe { self.tail.unwrap_unchecked() };
+
+ match multi.borrow_mut(tail) {
+ Ok(y) => {
+ let (((), head), tail) = y.finish();
+ HeadAndTail::Both(&mut head.data, &mut tail.data)
+ },
+ Err(n) => {
+ let ((), head) = n.finish();
+ HeadAndTail::One(&mut head.data)
+ }
+ }
+ }
+
+ pub fn all(&self) -> impl Iterator<Item = &T> {
+ let tok = self.noalias.ref_token();
+ Self::iter_ptrs(self.head, move |node| {
+ let node = node.borrow(tok);
+ (&node.data, node.next)
+ })
+ }
+
+ pub fn all_mut_safe(&mut self) -> impl Iterator<Item = &mut T> {
+ let mut multi = self.noalias.multi_runtime();
+ Self::iter_ptrs(self.head, move |node| {
+ let node = multi.borrow_mut(node).expect("untangled!");
+ (&mut node.data, node.next)
+ })
+ }
+
+ pub fn all_mut_fast(&mut self) -> impl Iterator<Item = &mut T> {
+ Self::iter_ptrs(self.head, |node| {
+ let tok = unsafe { MutToken::new_unchecked() };
+ let node = node.borrow_mut(tok);
+ (&mut node.data, node.next)
+ })
+ }
+
+ // We wouldn't do this, since it's daft, but
+ // it lets us demonstrate passing a token.
+ fn pop_front_inner<'a>(
+ mut tok: MutToken<'a>,
+ head: &mut Option<P<T>>,
+ tail: &mut Option<P<T>>,
+ ) -> Option<T> {
+ let deleting = (*head)?;
+ let new_head = deleting.borrow(&tok).next;
+ *head = new_head;
+ if let Some(new_head) = new_head {
+ new_head.borrow_mut(&mut tok).back = None;
+ } else {
+ *tail = None;
+ }
+ let deleted = unsafe { deleting.free_heap(&mut tok) };
+ Some(deleted.data)
+ }
+
+ fn iter_ptrs<'i, I: 'i>(
+ head: Option<P<T>>,
+ mut node_map: impl FnMut(P<T>) -> (I, Option<P<T>>) + 'i,
+ ) -> impl Iterator<Item = I> + 'i
+ where T: 'i
+ {
+ let mut next = head;
+ iter::from_fn(move || {
+ let node = next?;
+ let item;
+ (item, next) = node_map(node);
+ Some(item)
+ })
+ }
+}
+
+impl<T: Debug> Drop for List<T> {
+ fn drop(&mut self) {
+ while let Some(_) = Self::pop_front_inner(
+ self.noalias.mut_token(),
+ &mut self.head,
+ &mut self.tail,
+ ) { }
+ }
+}
+