ghost_gc/
arena.rs

1use std::alloc::{Allocator, Global};
2
3use crate::{
4    context::{Context, Pacing},
5    Collect, Mutation,
6};
7use alloc::boxed::Box;
8
9/// A garbage collected arena, inside which garbage collected pointers can be allocated.
10pub struct Arena<R: Rootable, A = Global>
11where
12    A: Allocator,
13{
14    context: Box<Context<A>>,
15    root: R::Root<'static>,
16}
17
18impl<R> Arena<R>
19where
20    R: Rootable,
21{
22    pub fn new<F>(f: F) -> Arena<R>
23    where
24        F: for<'b> FnOnce(&Mutation<'b>) -> R::Root<'b>,
25    {
26        Arena::new_in(f, Global)
27    }
28
29    pub fn new_paced<F>(f: F, pacing: Pacing) -> Arena<R>
30    where
31        F: for<'b> FnOnce(&Mutation<'b>) -> R::Root<'b>,
32    {
33        Arena::new_paced_in(f, pacing, Global)
34    }
35}
36
37impl<R, A> Arena<R, A>
38where
39    A: Allocator,
40    R: Rootable,
41{
42    pub fn new_in<F>(f: F, alloc: A) -> Arena<R, A>
43    where
44        F: for<'b> FnOnce(&Mutation<'b>) -> R::Root<'b>,
45        A: Allocator + 'static,
46    {
47        Arena::new_paced_in(f, Pacing::default(), alloc)
48    }
49
50    pub fn new_paced_in<F>(f: F, pacing: Pacing, alloc: A) -> Arena<R, A>
51    where
52        F: for<'b> FnOnce(&Mutation<'b>) -> R::Root<'b>,
53        A: Allocator + 'static,
54    {
55        let context: Box<Context<A>> = Box::new(Context::new_in(pacing, alloc));
56        let root = f(Mutation::new(&context));
57
58        Arena { context, root }
59    }
60
61    pub fn view<F, Ret>(&self, f: F) -> Ret
62    where
63        F: for<'b> FnOnce(&R::Root<'b>, &Mutation<'b>) -> Ret,
64    {
65        f(&self.root, Mutation::new(&self.context))
66    }
67
68    pub fn view_mut<F, Ret>(&mut self, f: F) -> Ret
69    where
70        F: for<'b> FnOnce(&mut R::Root<'b>, &Mutation<'b>) -> Ret,
71    {
72        self.context.set_root_untraced();
73        f(&mut self.root, Mutation::new(&self.context))
74    }
75
76    pub fn run_collection(&mut self) {
77        self.context.advance_collection(&self.root);
78    }
79
80    pub fn complete_collection(&mut self) {
81        self.context.run_full_cycle(&self.root);
82    }
83
84    pub fn allocations(&self) -> usize {
85        self.context.allocations()
86    }
87}
88
89pub trait Rootable {
90    type Root<'l>: Collect;
91}