arena/
lib.rs

1//! Arena
2//!
3//! An arena allows to allocate objects dynamically, and bind them to a
4//! specific common lifetime.
5//! All objects allocated on the arena live as long as the arena does.
6//! This allows us to easily link nodes together.
7//!
8//! # Example
9//! ```rust
10#![doc = include_str!("../examples/friends.rs")]
11//! ```
12
13mod chunk;
14mod dropless;
15mod typed;
16
17pub use dropless::DroplessArena;
18pub use typed::TypedArena;
19
20#[doc(hidden)]
21pub mod markers {
22    pub struct Copy;
23    pub struct NoCopy;
24}
25
26const PAGE_SIZE: usize = 4096;
27const HUGE_PAGE: usize = 2 * 1024 * 1024;
28
29#[macro_export]
30macro_rules! define_arenas {
31    ( $([visibility = $vis:vis ])? $(
32           $name:ident : $ty:ty
33    ),* $(,)?) => {
34
35        $($vis)? struct Arena<'ctx> {
36            dropless: $crate::DroplessArena<'ctx>,
37            $( $name:  $crate::TypedArena<'ctx, $ty>,)*
38        }
39
40        impl<'ctx> Arena<'ctx> {
41            $($vis)? fn new() -> Self {
42                Self {
43                    dropless: $crate::DroplessArena::default(),
44                    $(
45                        $name : $crate::TypedArena::default(),
46                    )*
47                }
48            }
49
50            $($vis)? fn alloc<T,C>(&self, val: T) -> &'ctx mut T
51            where
52                T: ArenaAllocable<'ctx, C>
53            {
54                val.alloc_into(self)
55            }
56
57            $($vis)? fn alloc_iter<T, I, C>(&self, val: I) -> &'ctx mut [T]
58            where
59                T: ArenaAllocable<'ctx, C>,
60                I: IntoIterator<Item = T>,
61                <I as IntoIterator>::IntoIter: ExactSizeIterator
62            {
63                T::alloc_iter(val, self)
64            }
65        }
66
67        $($vis)? trait ArenaAllocable<'ctx, C = $crate::markers::Copy> : Sized {
68            #[allow(clippy::mut_from_ref)]
69            fn alloc_into(self, arena: &Arena<'ctx>) -> &'ctx mut Self;
70
71            #[allow(clippy::mut_from_ref)]
72            fn alloc_iter<I>(it: I, arena: &Arena<'ctx>) -> &'ctx mut [Self]
73            where
74                I: IntoIterator<Item = Self>,
75                <I as IntoIterator>::IntoIter: ExactSizeIterator;
76        }
77
78        impl<'ctx, T: Copy> ArenaAllocable<'ctx> for T {
79            #[allow(clippy::mut_from_ref)]
80            fn alloc_into(self, arena: &Arena<'ctx>) ->  &'ctx mut Self {
81                arena.dropless.alloc(self)
82            }
83
84            #[allow(clippy::mut_from_ref)]
85            fn alloc_iter<I>(it:I, arena: &Arena<'ctx>) ->  &'ctx mut [Self]
86            where
87                I:IntoIterator<Item = Self>,
88                <I as IntoIterator>::IntoIter:ExactSizeIterator
89            {
90                arena.dropless.alloc_iter(it)
91            }
92        }
93
94        $(
95            impl<'ctx> ArenaAllocable<'ctx, $crate::markers::NoCopy> for $ty {
96                fn alloc_into(self, arena: &Arena<'ctx>) -> &'ctx mut Self {
97                    if !::core::mem::needs_drop::<Self>() {
98                        arena.dropless.alloc(self)
99                    } else {
100                        arena . $name .alloc(self)
101                    }
102                }
103
104                fn alloc_iter<I>(it: I, arena: &Arena<'ctx>) -> &'ctx mut [Self]
105                where
106                    I: IntoIterator<Item = Self>,
107                    <I as IntoIterator>::IntoIter: ExactSizeIterator
108                {
109                    if !::core::mem::needs_drop::<Self>() {
110                        arena.dropless.alloc_iter(it)
111                    } else {
112                        arena . $name .alloc_iter(it)
113                    }
114                }
115            }
116        )*
117    };
118}
119
120#[cfg(test)]
121mod test;