stack_graphs/
arena.rs

1// -*- coding: utf-8 -*-
2// ------------------------------------------------------------------------------------------------
3// Copyright © 2021, stack-graphs authors.
4// Licensed under either of Apache License, Version 2.0, or MIT license, at your option.
5// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
6// ------------------------------------------------------------------------------------------------
7
8//! Cache-friendly arena allocation for stack graph data.
9//!
10//! A stack graph is composed of instances of many different data types, and to store the graph
11//! structure itself, we need cyclic or self-referential data types.  The typical way to achieve
12//! this in Rust is to use [arena allocation][], where all of the instances of a particular type
13//! are stored in a single vector.  You then use indexes into this vector to store references to a
14//! data instance.  Because indexes are just numbers, you don't run afoul of borrow checker.  And
15//! because all instances live together in a continguous region of memory, your data access
16//! patterns are very cache-friendly.
17//!
18//! This module implements a simple arena allocation scheme for stack graphs.  An
19//! [`Arena<T>`][`Arena`] is an arena that holds all of the instances of type `T` for a stack
20//! graph.  A [`Handle<T>`][`Handle`] holds the index of a particular instance of `T` in its arena.
21//! All of our stack graph data types then use handles to refer to other parts of the stack graph.
22//!
23//! Note that our arena implementation does not support deletion!  Any content that you add to a
24//! [`StackGraph`][] will live as long as the stack graph itself does.  The entire region of memory
25//! for each arena will be freed in a single operation when the stack graph is dropped.
26//!
27//! [arena allocation]: https://en.wikipedia.org/wiki/Region-based_memory_management
28//! [`Arena`]: struct.Arena.html
29//! [`Handle`]: struct.Handle.html
30//! [`StackGraph`]: ../graph/struct.StackGraph.html
31
32use std::cell::Cell;
33use std::fmt::Debug;
34use std::hash::Hash;
35use std::hash::Hasher;
36use std::marker::PhantomData;
37use std::mem::MaybeUninit;
38use std::num::NonZeroU32;
39use std::ops::Index;
40use std::ops::IndexMut;
41
42use bitvec::vec::BitVec;
43use controlled_option::Niche;
44
45use crate::utils::cmp_option;
46use crate::utils::equals_option;
47
48//-------------------------------------------------------------------------------------------------
49// Arenas and handles
50
51/// A handle to an instance of type `T` that was allocated from an [`Arena`][].
52///
53/// #### Safety
54///
55/// Because of the type parameter `T`, the compiler can ensure that you don't use a handle for one
56/// type to index into an arena of another type.  However, if you have multiple arenas for the
57/// _same type_, we do not do anything to ensure that you only use a handle with the corresponding
58/// arena.
59#[repr(transparent)]
60pub struct Handle<T> {
61    index: NonZeroU32,
62    _phantom: PhantomData<T>,
63}
64
65impl<T> Handle<T> {
66    pub(crate) fn new(index: NonZeroU32) -> Handle<T> {
67        Handle {
68            index,
69            _phantom: PhantomData,
70        }
71    }
72
73    #[inline(always)]
74    pub fn as_u32(self) -> u32 {
75        self.index.get()
76    }
77
78    #[inline(always)]
79    pub fn as_usize(self) -> usize {
80        self.index.get() as usize
81    }
82}
83
84impl<T> Niche for Handle<T> {
85    type Output = u32;
86
87    #[inline]
88    fn none() -> Self::Output {
89        0
90    }
91
92    #[inline]
93    fn is_none(value: &Self::Output) -> bool {
94        *value == 0
95    }
96
97    #[inline]
98    fn into_some(value: Self) -> Self::Output {
99        value.index.get()
100    }
101
102    #[inline]
103    fn from_some(value: Self::Output) -> Self {
104        Self::new(unsafe { NonZeroU32::new_unchecked(value) })
105    }
106}
107
108// Normally we would #[derive] all of these traits, but the auto-derived implementations all
109// require that T implement the trait as well.  We don't store any real instances of T inside of
110// Handle, so our implementations do _not_ require that.
111
112impl<T> Clone for Handle<T> {
113    fn clone(&self) -> Handle<T> {
114        Handle::new(self.index)
115    }
116}
117
118impl<T> Copy for Handle<T> {}
119
120impl<T> Debug for Handle<T> {
121    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
122        f.debug_struct("Handle")
123            .field("index", &self.index)
124            .finish()
125    }
126}
127
128impl<T> Eq for Handle<T> {}
129
130impl<T> Hash for Handle<T> {
131    fn hash<H: Hasher>(&self, state: &mut H) {
132        self.index.hash(state);
133    }
134}
135
136impl<T> Ord for Handle<T> {
137    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
138        self.index.cmp(&other.index)
139    }
140}
141
142impl<T> PartialEq for Handle<T> {
143    fn eq(&self, other: &Self) -> bool {
144        self.index == other.index
145    }
146}
147
148impl<T> PartialOrd for Handle<T> {
149    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
150        self.index.partial_cmp(&other.index)
151    }
152}
153
154// Handles are always Send and Sync, even if the underlying types are not.  After all, a handle is
155// just a number!  And you _also_ need access to the Arena (which _won't_ be Send/Sync if T isn't)
156// to dereference the handle.
157unsafe impl<T> Send for Handle<T> {}
158unsafe impl<T> Sync for Handle<T> {}
159
160/// Manages the life cycle of instances of type `T`.  You can allocate new instances of `T` from
161/// the arena.  All of the instances managed by this arena will be dropped as a single operation
162/// when the arena itself is dropped.
163pub struct Arena<T> {
164    items: Vec<MaybeUninit<T>>,
165}
166
167impl<T> Drop for Arena<T> {
168    fn drop(&mut self) {
169        unsafe {
170            let items = std::mem::transmute::<_, &mut [T]>(&mut self.items[1..]) as *mut [T];
171            items.drop_in_place();
172        }
173    }
174}
175
176impl<T> Arena<T> {
177    /// Creates a new arena.
178    pub fn new() -> Arena<T> {
179        Arena {
180            items: vec![MaybeUninit::uninit()],
181        }
182    }
183
184    /// Clear the arena, keeping underlying allocated capacity.  After this, all previous handles into
185    /// the arena are invalid.
186    #[inline(always)]
187    pub fn clear(&mut self) {
188        self.items.truncate(1);
189    }
190
191    /// Adds a new instance to this arena, returning a stable handle to it.
192    ///
193    /// Note that we do not deduplicate instances of `T` in any way.  If you add two instances that
194    /// have the same content, you will get distinct handles for each one.
195    pub fn add(&mut self, item: T) -> Handle<T> {
196        let index = self.items.len() as u32;
197        self.items.push(MaybeUninit::new(item));
198        Handle::new(unsafe { NonZeroU32::new_unchecked(index) })
199    }
200
201    /// Dereferences a handle to an instance owned by this arena, returning a reference to it.
202    pub fn get(&self, handle: Handle<T>) -> &T {
203        unsafe { std::mem::transmute(&self.items[handle.as_usize()]) }
204    }
205    ///
206    /// Dereferences a handle to an instance owned by this arena, returning a mutable reference to
207    /// it.
208    pub fn get_mut(&mut self, handle: Handle<T>) -> &mut T {
209        unsafe { std::mem::transmute(&mut self.items[handle.as_usize()]) }
210    }
211
212    /// Returns an iterator of all of the handles in this arena.  (Note that this iterator does not
213    /// retain a reference to the arena!)
214    pub fn iter_handles(&self) -> impl Iterator<Item = Handle<T>> {
215        (1..self.items.len())
216            .into_iter()
217            .map(|index| Handle::new(unsafe { NonZeroU32::new_unchecked(index as u32) }))
218    }
219
220    /// Returns a pointer to this arena's storage.
221    pub(crate) fn as_ptr(&self) -> *const T {
222        self.items.as_ptr() as *const T
223    }
224
225    /// Returns the number of instances stored in this arena.
226    #[inline(always)]
227    pub fn len(&self) -> usize {
228        self.items.len()
229    }
230}
231
232//-------------------------------------------------------------------------------------------------
233// Supplemental arenas
234
235/// A supplemental arena lets you store additional data about some data type that is itself stored
236/// in an [`Arena`][].
237///
238/// We implement `Index` and `IndexMut` for a more ergonomic syntax.  Please note that when
239/// indexing in an _immutable_ context, we **_panic_** if you try to access data for a handle that
240/// doesn't exist in the arena.  (Use the [`get`][] method if you don't know whether the value
241/// exists or not.)  In a _mutable_ context, we automatically create a `Default` instance of the
242/// type if there isn't already an instance for that handle in the arena.
243///
244/// ```
245/// # use stack_graphs::arena::Arena;
246/// # use stack_graphs::arena::SupplementalArena;
247/// // We need an Arena to create handles.
248/// let mut arena = Arena::<u32>::new();
249/// let handle = arena.add(1);
250///
251/// let mut supplemental = SupplementalArena::<u32, String>::new();
252///
253/// // But indexing will panic if the element doesn't already exist.
254/// // assert_eq!(supplemental[handle].as_str(), "");
255///
256/// // The `get` method is always safe, since it returns an Option.
257/// assert_eq!(supplemental.get(handle), None);
258///
259/// // Once we've added the element to the supplemental arena, indexing
260/// // won't panic anymore.
261/// supplemental[handle] = "hello".to_string();
262/// assert_eq!(supplemental[handle].as_str(), "hello");
263/// ```
264///
265/// [`Arena`]: struct.Arena.html
266/// [`get`]: #method.get
267pub struct SupplementalArena<H, T> {
268    items: Vec<MaybeUninit<T>>,
269    _phantom: PhantomData<H>,
270}
271
272impl<H, T> Drop for SupplementalArena<H, T> {
273    fn drop(&mut self) {
274        unsafe {
275            let items = std::mem::transmute::<_, &mut [T]>(&mut self.items[1..]) as *mut [T];
276            items.drop_in_place();
277        }
278    }
279}
280
281impl<H, T> SupplementalArena<H, T> {
282    /// Creates a new, empty supplemental arena.
283    pub fn new() -> SupplementalArena<H, T> {
284        SupplementalArena {
285            items: vec![MaybeUninit::uninit()],
286            _phantom: PhantomData,
287        }
288    }
289
290    /// Clear the supplemantal arena, keeping underlying allocated capacity.  After this,
291    /// all previous handles into the arena are invalid.
292    #[inline(always)]
293    pub fn clear(&mut self) {
294        self.items.truncate(1);
295    }
296
297    /// Creates a new, empty supplemental arena, preallocating enough space to store supplemental
298    /// data for all of the instances that have already been allocated in a (regular) arena.
299    pub fn with_capacity(arena: &Arena<H>) -> SupplementalArena<H, T> {
300        let mut items = Vec::with_capacity(arena.items.len());
301        items[0] = MaybeUninit::uninit();
302        SupplementalArena {
303            items,
304            _phantom: PhantomData,
305        }
306    }
307
308    /// Returns the item belonging to a particular handle, if it exists.
309    pub fn get(&self, handle: Handle<H>) -> Option<&T> {
310        self.items
311            .get(handle.as_usize())
312            .map(|x| unsafe { &*(x.as_ptr()) })
313    }
314
315    /// Returns a mutable reference to the item belonging to a particular handle, if it exists.
316    pub fn get_mut(&mut self, handle: Handle<H>) -> Option<&mut T> {
317        self.items
318            .get_mut(handle.as_usize())
319            .map(|x| unsafe { &mut *(x.as_mut_ptr()) })
320    }
321
322    /// Returns a pointer to this arena's storage.
323    pub(crate) fn as_ptr(&self) -> *const T {
324        self.items.as_ptr() as *const T
325    }
326
327    /// Returns the number of instances stored in this arena.
328    #[inline(always)]
329    pub fn len(&self) -> usize {
330        self.items.len()
331    }
332
333    /// Iterate over the items in this arena.
334    pub(crate) fn iter(&self) -> impl Iterator<Item = (Handle<T>, &T)> {
335        self.items
336            .iter()
337            .enumerate()
338            .skip(1)
339            .map(|(i, x)| (Handle::from_some(i as u32), unsafe { &*(x.as_ptr()) }))
340    }
341}
342
343impl<H, T> SupplementalArena<H, T>
344where
345    T: Default,
346{
347    /// Returns a mutable reference to the item belonging to a particular handle, creating it first
348    /// (using the type's `Default` implementation) if it doesn't already exist.
349    pub fn get_mut_or_default(&mut self, handle: Handle<H>) -> &mut T {
350        let index = handle.as_usize();
351        if self.items.len() <= index {
352            self.items
353                .resize_with(index + 1, || MaybeUninit::new(T::default()));
354        }
355        unsafe { std::mem::transmute(&mut self.items[handle.as_usize()]) }
356    }
357}
358
359impl<H, T> Default for SupplementalArena<H, T> {
360    fn default() -> SupplementalArena<H, T> {
361        SupplementalArena::new()
362    }
363}
364
365impl<H, T> Index<Handle<H>> for SupplementalArena<H, T> {
366    type Output = T;
367    fn index(&self, handle: Handle<H>) -> &T {
368        unsafe { std::mem::transmute(&self.items[handle.as_usize()]) }
369    }
370}
371
372impl<H, T> IndexMut<Handle<H>> for SupplementalArena<H, T>
373where
374    T: Default,
375{
376    fn index_mut(&mut self, handle: Handle<H>) -> &mut T {
377        self.get_mut_or_default(handle)
378    }
379}
380
381//-------------------------------------------------------------------------------------------------
382// Handle sets
383
384/// Contains a set of handles, encoded efficiently using a bit set.
385#[repr(C)]
386pub struct HandleSet<T> {
387    elements: BitVec<u32, bitvec::order::Lsb0>,
388    _phantom: PhantomData<T>,
389}
390
391impl<T> HandleSet<T> {
392    /// Creates a new, empty handle set.
393    pub fn new() -> HandleSet<T> {
394        HandleSet::default()
395    }
396
397    /// Removes all elements from this handle set.
398    pub fn clear(&mut self) {
399        self.elements.clear();
400    }
401
402    /// Returns whether this set contains a particular handle.
403    pub fn contains(&self, handle: Handle<T>) -> bool {
404        let index = handle.as_usize();
405        self.elements.get(index).map(|bit| *bit).unwrap_or(false)
406    }
407
408    /// Adds a handle to this set.
409    pub fn add(&mut self, handle: Handle<T>) {
410        let index = handle.as_usize();
411        if self.elements.len() <= index {
412            self.elements.resize(index + 1, false);
413        }
414        let mut bit = unsafe { self.elements.get_unchecked_mut(index) };
415        *bit = true;
416    }
417
418    /// Removes a handle from this set.
419    pub fn remove(&mut self, handle: Handle<T>) {
420        let index = handle.as_usize();
421        if let Some(mut bit) = self.elements.get_mut(index) {
422            *bit = false;
423        }
424    }
425
426    /// Returns an iterator of all of the handles in this set.
427    pub fn iter(&self) -> impl Iterator<Item = Handle<T>> + '_ {
428        self.elements
429            .iter_ones()
430            .map(|index| Handle::new(unsafe { NonZeroU32::new_unchecked(index as u32) }))
431    }
432
433    /// Returns a pointer to this set's storage.
434    pub(crate) fn as_ptr(&self) -> *const u32 {
435        self.elements.as_bitptr().pointer()
436    }
437
438    /// Returns the number of instances stored in this arena.
439    #[inline(always)]
440    pub(crate) fn len(&self) -> usize {
441        self.elements.as_raw_slice().len()
442    }
443}
444
445impl<T> Default for HandleSet<T> {
446    fn default() -> HandleSet<T> {
447        HandleSet {
448            elements: BitVec::default(),
449            _phantom: PhantomData,
450        }
451    }
452}
453
454//-------------------------------------------------------------------------------------------------
455// Arena-allocated lists
456
457/// An arena-allocated singly-linked list.
458///
459/// Linked lists are often a poor choice because they aren't very cache-friendly.  However, this
460/// linked list implementation _should_ be cache-friendly, since the individual cells are allocated
461/// out of an arena.
462#[repr(C)]
463#[derive(Niche)]
464pub struct List<T> {
465    // The value of this handle will be EMPTY_LIST_HANDLE if the list is empty.  For an
466    // Option<List<T>>, the value will be zero (via the Option<NonZero> optimization) if the list
467    // is None.
468    #[niche]
469    cells: Handle<ListCell<T>>,
470}
471
472#[doc(hidden)]
473#[repr(C)]
474pub struct ListCell<T> {
475    head: T,
476    // The value of this handle will be EMPTY_LIST_HANDLE if this is the last element of the list.
477    tail: Handle<ListCell<T>>,
478}
479
480const EMPTY_LIST_HANDLE: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(u32::MAX) };
481
482// An arena that's used to manage `List<T>` instances.
483//
484// (Note that the arena doesn't store `List<T>` itself; it stores the `ListCell<T>`s that the lists
485// are made of.)
486pub type ListArena<T> = Arena<ListCell<T>>;
487
488impl<T> List<T> {
489    /// Creates a new `ListArena` that will manage lists of this type.
490    pub fn new_arena() -> ListArena<T> {
491        ListArena::new()
492    }
493
494    /// Returns whether this list is empty.
495    #[inline(always)]
496    pub fn is_empty(&self) -> bool {
497        self.cells.index == EMPTY_LIST_HANDLE
498    }
499
500    /// Returns an empty list.
501    pub fn empty() -> List<T> {
502        List {
503            cells: Handle::new(EMPTY_LIST_HANDLE),
504        }
505    }
506
507    pub fn from_handle(handle: Handle<ListCell<T>>) -> List<T> {
508        List { cells: handle }
509    }
510
511    /// Returns a handle to the head of the list.
512    pub fn handle(&self) -> Handle<ListCell<T>> {
513        self.cells
514    }
515
516    /// Pushes a new element onto the front of this list.
517    pub fn push_front(&mut self, arena: &mut ListArena<T>, head: T) {
518        self.cells = arena.add(ListCell {
519            head,
520            tail: self.cells,
521        });
522    }
523
524    /// Removes and returns the element at the front of this list.  If the list is empty, returns
525    /// `None`.
526    pub fn pop_front<'a>(&mut self, arena: &'a ListArena<T>) -> Option<&'a T> {
527        if self.is_empty() {
528            return None;
529        }
530        let cell = arena.get(self.cells);
531        self.cells = cell.tail;
532        Some(&cell.head)
533    }
534
535    /// Returns an iterator over the elements of this list.
536    pub fn iter<'a>(mut self, arena: &'a ListArena<T>) -> impl Iterator<Item = &'a T> + 'a {
537        std::iter::from_fn(move || self.pop_front(arena))
538    }
539}
540
541impl<T> List<T> {
542    pub fn equals_with<F>(mut self, arena: &ListArena<T>, mut other: List<T>, mut eq: F) -> bool
543    where
544        F: FnMut(&T, &T) -> bool,
545    {
546        loop {
547            if self.cells == other.cells {
548                return true;
549            }
550            if !equals_option(self.pop_front(arena), other.pop_front(arena), &mut eq) {
551                return false;
552            }
553        }
554    }
555
556    pub fn cmp_with<F>(
557        mut self,
558        arena: &ListArena<T>,
559        mut other: List<T>,
560        mut cmp: F,
561    ) -> std::cmp::Ordering
562    where
563        F: FnMut(&T, &T) -> std::cmp::Ordering,
564    {
565        use std::cmp::Ordering;
566        loop {
567            if self.cells == other.cells {
568                return Ordering::Equal;
569            }
570            match cmp_option(self.pop_front(arena), other.pop_front(arena), &mut cmp) {
571                Ordering::Equal => (),
572                result @ _ => return result,
573            }
574        }
575    }
576}
577
578impl<T> List<T>
579where
580    T: Eq,
581{
582    pub fn equals(self, arena: &ListArena<T>, other: List<T>) -> bool {
583        self.equals_with(arena, other, |a, b| *a == *b)
584    }
585}
586
587impl<T> List<T>
588where
589    T: Ord,
590{
591    pub fn cmp(self, arena: &ListArena<T>, other: List<T>) -> std::cmp::Ordering {
592        self.cmp_with(arena, other, |a, b| a.cmp(b))
593    }
594}
595
596// Normally we would #[derive] all of these traits, but the auto-derived implementations all
597// require that T implement the trait as well.  We don't store any real instances of T inside of
598// List, so our implementations do _not_ require that.
599
600impl<T> Clone for List<T> {
601    fn clone(&self) -> List<T> {
602        List { cells: self.cells }
603    }
604}
605
606impl<T> Copy for List<T> {}
607
608//-------------------------------------------------------------------------------------------------
609// Reversible arena-allocated list
610
611/// An arena-allocated list that can be reversed.
612///
613/// Well, that is, you can reverse a [`List`][] just fine by yourself.  This type takes care of
614/// doing that for you, and importantly, _saves the result_ so that if you only have to compute the
615/// reversal once even if you need to access it multiple times.
616///
617/// [`List`]: struct.List.html
618#[repr(C)]
619#[derive(Niche)]
620pub struct ReversibleList<T> {
621    #[niche]
622    cells: Handle<ReversibleListCell<T>>,
623}
624
625#[repr(C)]
626#[doc(hidden)]
627pub struct ReversibleListCell<T> {
628    head: T,
629    tail: Handle<ReversibleListCell<T>>,
630    reversed: Cell<Option<Handle<ReversibleListCell<T>>>>,
631}
632
633// An arena that's used to manage `ReversibleList<T>` instances.
634//
635// (Note that the arena doesn't store `ReversibleList<T>` itself; it stores the
636// `ReversibleListCell<T>`s that the lists are made of.)
637pub type ReversibleListArena<T> = Arena<ReversibleListCell<T>>;
638
639impl<T> ReversibleList<T> {
640    /// Creates a new `ReversibleListArena` that will manage lists of this type.
641    pub fn new_arena() -> ReversibleListArena<T> {
642        ReversibleListArena::new()
643    }
644
645    /// Returns whether this list is empty.
646    #[inline(always)]
647    pub fn is_empty(&self) -> bool {
648        ReversibleListCell::is_empty_handle(self.cells)
649    }
650
651    /// Returns an empty list.
652    pub fn empty() -> ReversibleList<T> {
653        ReversibleList {
654            cells: ReversibleListCell::empty_handle(),
655        }
656    }
657
658    /// Returns whether we have already calculated the reversal of this list.
659    pub fn have_reversal(&self, arena: &ReversibleListArena<T>) -> bool {
660        if self.is_empty() {
661            // The empty list is already reversed.
662            return true;
663        }
664        arena.get(self.cells).reversed.get().is_some()
665    }
666
667    /// Pushes a new element onto the front of this list.
668    pub fn push_front(&mut self, arena: &mut ReversibleListArena<T>, head: T) {
669        self.cells = arena.add(ReversibleListCell::new(head, self.cells, None));
670    }
671
672    /// Removes and returns the element at the front of this list.  If the list is empty, returns
673    /// `None`.
674    pub fn pop_front<'a>(&mut self, arena: &'a ReversibleListArena<T>) -> Option<&'a T> {
675        if self.is_empty() {
676            return None;
677        }
678        let cell = arena.get(self.cells);
679        self.cells = cell.tail;
680        Some(&cell.head)
681    }
682
683    /// Returns an iterator over the elements of this list.
684    pub fn iter<'a>(
685        mut self,
686        arena: &'a ReversibleListArena<T>,
687    ) -> impl Iterator<Item = &'a T> + 'a {
688        std::iter::from_fn(move || self.pop_front(arena))
689    }
690}
691
692impl<T> ReversibleList<T>
693where
694    T: Clone,
695{
696    /// Reverses the list.  Since we're already caching everything in an arena, we make sure to
697    /// only calculate the reversal once, returning it as-is if you call this function multiple
698    /// times.
699    pub fn reverse(&mut self, arena: &mut ReversibleListArena<T>) {
700        if self.is_empty() {
701            return;
702        }
703        self.ensure_reversal_available(arena);
704        self.cells = arena.get(self.cells).reversed.get().unwrap();
705    }
706
707    /// Ensures that the reversal of this list is available.  It can be useful to precalculate this
708    /// when you have mutable access to the arena, so that you can then reverse and un-reverse the
709    /// list later when you only have shared access to it.
710    pub fn ensure_reversal_available(&mut self, arena: &mut ReversibleListArena<T>) {
711        // First check to see if the list has already been reversed.
712        if self.is_empty() {
713            // The empty list is already reversed.
714            return;
715        }
716        if arena.get(self.cells).reversed.get().is_some() {
717            return;
718        }
719
720        // If not, reverse the list and cache the result.
721        let new_reversed = ReversibleListCell::reverse(self.cells, arena);
722        arena.get(self.cells).reversed.set(Some(new_reversed));
723    }
724}
725
726impl<T> ReversibleList<T> {
727    /// Reverses the list, assuming that the reversal has already been computed.  If it hasn't we
728    /// return an error.
729    pub fn reverse_reused(&mut self, arena: &ReversibleListArena<T>) -> Result<(), ()> {
730        if self.is_empty() {
731            // The empty list is already reversed.
732            return Ok(());
733        }
734        self.cells = arena.get(self.cells).reversed.get().ok_or(())?;
735        Ok(())
736    }
737}
738
739impl<T> ReversibleListCell<T> {
740    fn new(
741        head: T,
742        tail: Handle<ReversibleListCell<T>>,
743        reversed: Option<Handle<ReversibleListCell<T>>>,
744    ) -> ReversibleListCell<T> {
745        ReversibleListCell {
746            head,
747            tail,
748            reversed: Cell::new(reversed),
749        }
750    }
751
752    fn empty_handle() -> Handle<ReversibleListCell<T>> {
753        Handle::new(EMPTY_LIST_HANDLE)
754    }
755
756    fn is_empty_handle(handle: Handle<ReversibleListCell<T>>) -> bool {
757        handle.index == EMPTY_LIST_HANDLE
758    }
759}
760
761impl<T> ReversibleListCell<T>
762where
763    T: Clone,
764{
765    fn reverse(
766        forwards: Handle<ReversibleListCell<T>>,
767        arena: &mut ReversibleListArena<T>,
768    ) -> Handle<ReversibleListCell<T>> {
769        let mut reversed = ReversibleListCell::empty_handle();
770        let mut current = forwards;
771        while !ReversibleListCell::is_empty_handle(current) {
772            let cell = arena.get(current);
773            let head = cell.head.clone();
774            current = cell.tail;
775            reversed = arena.add(Self::new(
776                head,
777                reversed,
778                // The reversal of the reversal that we just calculated is our original list!  Go
779                // ahead and cache that away preemptively.
780                if ReversibleListCell::is_empty_handle(current) {
781                    Some(forwards)
782                } else {
783                    None
784                },
785            ));
786        }
787        reversed
788    }
789}
790
791impl<T> ReversibleList<T> {
792    pub fn equals_with<F>(
793        mut self,
794        arena: &ReversibleListArena<T>,
795        mut other: ReversibleList<T>,
796        mut eq: F,
797    ) -> bool
798    where
799        F: FnMut(&T, &T) -> bool,
800    {
801        loop {
802            if self.cells == other.cells {
803                return true;
804            }
805            if !equals_option(self.pop_front(arena), other.pop_front(arena), &mut eq) {
806                return false;
807            }
808        }
809    }
810
811    pub fn cmp_with<F>(
812        mut self,
813        arena: &ReversibleListArena<T>,
814        mut other: ReversibleList<T>,
815        mut cmp: F,
816    ) -> std::cmp::Ordering
817    where
818        F: FnMut(&T, &T) -> std::cmp::Ordering,
819    {
820        use std::cmp::Ordering;
821        loop {
822            if self.cells == other.cells {
823                return Ordering::Equal;
824            }
825            match cmp_option(self.pop_front(arena), other.pop_front(arena), &mut cmp) {
826                Ordering::Equal => (),
827                result @ _ => return result,
828            }
829        }
830    }
831}
832
833impl<T> ReversibleList<T>
834where
835    T: Eq,
836{
837    pub fn equals(self, arena: &ReversibleListArena<T>, other: ReversibleList<T>) -> bool {
838        self.equals_with(arena, other, |a, b| *a == *b)
839    }
840}
841
842impl<T> ReversibleList<T>
843where
844    T: Ord,
845{
846    pub fn cmp(
847        self,
848        arena: &ReversibleListArena<T>,
849        other: ReversibleList<T>,
850    ) -> std::cmp::Ordering {
851        self.cmp_with(arena, other, |a, b| a.cmp(b))
852    }
853}
854
855// Normally we would #[derive] all of these traits, but the auto-derived implementations all
856// require that T implement the trait as well.  We don't store any real instances of T inside of
857// ReversibleList, so our implementations do _not_ require that.
858
859impl<T> Clone for ReversibleList<T> {
860    fn clone(&self) -> ReversibleList<T> {
861        ReversibleList { cells: self.cells }
862    }
863}
864
865impl<T> Copy for ReversibleList<T> {}
866
867//-------------------------------------------------------------------------------------------------
868// Arena-allocated deque
869
870/// An arena-allocated deque.
871///
872/// Under the covers, this is implemented as a [`List`][].  Because these lists are singly-linked,
873/// we can only add elements to, and remove them from, one side of the list.
874///
875/// To handle this, each deque stores its contents either _forwards_ or _backwards_.  We
876/// automatically shift between these two representations as needed, depending on the requirements
877/// of each method.
878///
879/// Note that we cache the result of reversing the list, so it should be quick to switch back and
880/// forth between representations _as long as you have not added any additional elements to the
881/// deque_!  If performance is critical, you should ensure that you don't call methods in a pattern
882/// that causes the deque to reverse itself each time you add an element.
883///
884/// [`List`]: struct.List.html
885#[repr(C)]
886#[derive(Niche)]
887pub struct Deque<T> {
888    #[niche]
889    list: ReversibleList<T>,
890    direction: DequeDirection,
891}
892
893#[repr(C)]
894#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
895enum DequeDirection {
896    Forwards,
897    Backwards,
898}
899
900impl std::ops::Not for DequeDirection {
901    type Output = DequeDirection;
902    fn not(self) -> DequeDirection {
903        match self {
904            DequeDirection::Forwards => DequeDirection::Backwards,
905            DequeDirection::Backwards => DequeDirection::Forwards,
906        }
907    }
908}
909
910// An arena that's used to manage `Deque<T>` instances.
911pub type DequeArena<T> = ReversibleListArena<T>;
912
913impl<T> Deque<T> {
914    /// Creates a new `DequeArena` that will manage deques of this type.
915    pub fn new_arena() -> DequeArena<T> {
916        ReversibleList::new_arena()
917    }
918
919    /// Returns whether this deque is empty.
920    #[inline(always)]
921    pub fn is_empty(&self) -> bool {
922        self.list.is_empty()
923    }
924
925    /// Returns an empty deque.
926    pub fn empty() -> Deque<T> {
927        Deque {
928            list: ReversibleList::empty(),
929            // A philosophical question for you: is the empty list forwards or backwards?  It
930            // doesn't really matter which one we choose here; if we immediately start pushing onto
931            // the back, we'll "reverse" the current list before proceeding, but reversing the
932            // empty list is a no-op.
933            direction: DequeDirection::Forwards,
934        }
935    }
936
937    /// Returns whether we have already calculated the reversal of this deque.
938    pub fn have_reversal(&self, arena: &DequeArena<T>) -> bool {
939        self.list.have_reversal(arena)
940    }
941
942    fn is_backwards(&self) -> bool {
943        matches!(self.direction, DequeDirection::Backwards)
944    }
945
946    fn is_forwards(&self) -> bool {
947        matches!(self.direction, DequeDirection::Forwards)
948    }
949
950    /// Returns an iterator over the contents of this deque, with no guarantee about the ordering of
951    /// the elements.  (By not caring about the ordering of the elements, you can call this method
952    /// regardless of which direction the deque's elements are currently stored.  And that, in
953    /// turn, means that we only need shared access to the arena, and not mutable access to it.)
954    pub fn iter_unordered<'a>(&self, arena: &'a DequeArena<T>) -> impl Iterator<Item = &'a T> + 'a {
955        self.list.iter(arena)
956    }
957}
958
959impl<T> Deque<T>
960where
961    T: Clone,
962{
963    /// Ensures that this deque has computed its backwards-facing list of elements.
964    pub fn ensure_backwards(&mut self, arena: &mut DequeArena<T>) {
965        if self.is_backwards() {
966            return;
967        }
968        self.list.reverse(arena);
969        self.direction = DequeDirection::Backwards;
970    }
971
972    /// Ensures that this deque has computed its forwards-facing list of elements.
973    pub fn ensure_forwards(&mut self, arena: &mut DequeArena<T>) {
974        if self.is_forwards() {
975            return;
976        }
977        self.list.reverse(arena);
978        self.direction = DequeDirection::Forwards;
979    }
980
981    /// Pushes a new element onto the front of this deque.
982    pub fn push_front(&mut self, arena: &mut DequeArena<T>, element: T) {
983        self.ensure_forwards(arena);
984        self.list.push_front(arena, element);
985    }
986
987    /// Pushes a new element onto the back of this deque.
988    pub fn push_back(&mut self, arena: &mut DequeArena<T>, element: T) {
989        self.ensure_backwards(arena);
990        self.list.push_front(arena, element);
991    }
992
993    /// Removes and returns the element from the front of this deque.  If the deque is empty,
994    /// returns `None`.
995    pub fn pop_front<'a>(&mut self, arena: &'a mut DequeArena<T>) -> Option<&'a T> {
996        self.ensure_forwards(arena);
997        self.list.pop_front(arena)
998    }
999
1000    /// Removes and returns the element from the back of this deque.  If the deque is empty,
1001    /// returns `None`.
1002    pub fn pop_back<'a>(&mut self, arena: &'a mut DequeArena<T>) -> Option<&'a T> {
1003        self.ensure_backwards(arena);
1004        self.list.pop_front(arena)
1005    }
1006
1007    /// Returns an iterator over the contents of this deque in a forwards direction.
1008    pub fn iter<'a>(&self, arena: &'a mut DequeArena<T>) -> impl Iterator<Item = &'a T> + 'a {
1009        let mut list = self.list;
1010        if self.is_backwards() {
1011            list.reverse(arena);
1012        }
1013        list.iter(arena)
1014    }
1015
1016    /// Returns an iterator over the contents of this deque in a backwards direction.
1017    pub fn iter_reversed<'a>(
1018        &self,
1019        arena: &'a mut DequeArena<T>,
1020    ) -> impl Iterator<Item = &'a T> + 'a {
1021        let mut list = self.list;
1022        if self.is_forwards() {
1023            list.reverse(arena);
1024        }
1025        list.iter(arena)
1026    }
1027
1028    /// Ensures that both deques are stored in the same direction.  It doesn't matter _which_
1029    /// direction, as long as they're the same, so do the minimum amount of work to bring this
1030    /// about.  (In particular, if we've already calculated the reversal of one of the deques,
1031    /// reverse that one.)
1032    fn ensure_same_direction(&mut self, arena: &mut DequeArena<T>, other: &mut Deque<T>) {
1033        if self.direction == other.direction {
1034            return;
1035        }
1036        if self.list.have_reversal(arena) {
1037            self.list.reverse(arena);
1038            self.direction = !self.direction;
1039        } else {
1040            other.list.reverse(arena);
1041            other.direction = !other.direction;
1042        }
1043    }
1044}
1045
1046impl<T> Deque<T>
1047where
1048    T: Clone,
1049{
1050    pub fn equals_with<F>(mut self, arena: &mut DequeArena<T>, mut other: Deque<T>, eq: F) -> bool
1051    where
1052        F: FnMut(&T, &T) -> bool,
1053    {
1054        self.ensure_same_direction(arena, &mut other);
1055        self.list.equals_with(arena, other.list, eq)
1056    }
1057
1058    pub fn cmp_with<F>(
1059        mut self,
1060        arena: &mut DequeArena<T>,
1061        mut other: Deque<T>,
1062        cmp: F,
1063    ) -> std::cmp::Ordering
1064    where
1065        F: FnMut(&T, &T) -> std::cmp::Ordering,
1066    {
1067        // To compare, we need boths deques to specifically be pointing forwards, and not just in
1068        // the same direction, so that we get the lexicographic comparison correct.
1069        self.ensure_forwards(arena);
1070        other.ensure_forwards(arena);
1071        self.list.cmp_with(arena, other.list, cmp)
1072    }
1073}
1074
1075impl<T> Deque<T>
1076where
1077    T: Clone + Eq,
1078{
1079    pub fn equals(self, arena: &mut DequeArena<T>, other: Deque<T>) -> bool {
1080        self.equals_with(arena, other, |a, b| *a == *b)
1081    }
1082}
1083
1084impl<T> Deque<T>
1085where
1086    T: Clone + Ord,
1087{
1088    pub fn cmp(self, arena: &mut DequeArena<T>, other: Deque<T>) -> std::cmp::Ordering {
1089        self.cmp_with(arena, other, |a, b| a.cmp(b))
1090    }
1091}
1092
1093impl<T> Deque<T> {
1094    /// Returns an iterator over the contents of this deque in a forwards direction, assuming that
1095    /// we have already computed its forwards-facing list of elements via [`ensure_forwards`][].
1096    /// Panics if we haven't already computed it.
1097    ///
1098    /// [`ensure_forwards`]: #method.ensure_forwards
1099    pub fn iter_reused<'a>(&self, arena: &'a DequeArena<T>) -> impl Iterator<Item = &'a T> + 'a {
1100        let mut list = self.list;
1101        if self.is_backwards() {
1102            list.reverse_reused(arena)
1103                .expect("Forwards deque hasn't been calculated");
1104        }
1105        list.iter(arena)
1106    }
1107
1108    /// Returns an iterator over the contents of this deque in a backwards direction, assuming that
1109    /// we have already computed its backwards-facing list of elements via [`ensure_backwards`][].
1110    /// Panics if we haven't already computed it.
1111    ///
1112    /// [`ensure_backwards`]: #method.ensure_backwards
1113    pub fn iter_reversed_reused<'a>(
1114        &self,
1115        arena: &'a DequeArena<T>,
1116    ) -> impl Iterator<Item = &'a T> + 'a {
1117        let mut list = self.list;
1118        if self.is_forwards() {
1119            list.reverse_reused(arena)
1120                .expect("Backwards deque hasn't been calculated");
1121        }
1122        list.iter(arena)
1123    }
1124}
1125
1126// Normally we would #[derive] all of these traits, but the auto-derived implementations all
1127// require that T implement the trait as well.  We don't store any real instances of T inside of
1128// Deque, so our implementations do _not_ require that.
1129
1130impl<T> Clone for Deque<T> {
1131    fn clone(&self) -> Deque<T> {
1132        Deque {
1133            list: self.list,
1134            direction: self.direction,
1135        }
1136    }
1137}
1138
1139impl<T> Copy for Deque<T> {}