Expand description
A concurrent, generational, trace and sweep garbage collected arena.
§Creating An Arena
All garbage collection in Sandpit happens within an arena. Therefore, to be begin we can start with creating a new arena.
This can be done like so..
use sandpit::{Arena, Root};
// This creates an arena with a `MyRoot` as the root.
let gc: Arena<Root![MyRoot]> = Arena::new(|mutator| {
MyRoot::new(mutator)
});
There are two big things to unpack here:
- An
Arena
is generic on its single Root value which it holds. - The Root of an
Arena
must be a Higher Kinded Type(HKT).
This is explained in much further depth in sandpit::Arena
.
§Trace Trait
For a type to be GC’ed it is required to impl Trace
which can be safely derived as long as all inner types also impl Trace
.
use sandpit::{Trace, gc::{Gc, GcMut, GcOpt}};
#[derive(Trace)]
enum Value<'gc> {
// GC values must be branded with a mutation lifetime
// to ensure freeing memory can happen safely.
A(Gc<'gc, A>), // Immutable pointer, essentially a &'gc T.
B(GcMut<'gc, B>), // Mutable pointer, can be updated to point at something else via a write barrier.
C(GcOpt<'gc, C>), // Optionally null pointer that is also mutable. Can be unwrapped into a GcMut.
}
// All inner values must be trace, therefore types A, B, and T must impl Trace as well!
Essentially when a value is traced the tracer will mark the value as live, and call trace on all its inner pointers to GC values.
There are 3 types of GC pointers:
A type may also derive TraceLeaf
, if it contains no GC pointers.
TraceLeaf
allows for easier interior mutability.
§Mutating the Arena
Once you have your arena and your traceable types, you can begin allocating
them in the arena by calling Arena::mutate
. Within a mutation
we can essentially do 3 important things:
- Access all data reaachable from the root.
- Create new garbage collected values.
- Update Gc pointers to point to new values via a
WriteBarrier
.
use sandpit::{Trace, gc::GcMut};
arena.mutate(|mutator, root| {
// We can access everything reachable from the root.
traverse(root);
// We can allocate new Gc values.
// Here is a pointer, to a pointer, to a bool!
let gc_mut = GcMut::new(mutator,
GcMut::new(mutator, true)
);
// We can mutate existing inner GcMut and GcOpt pointers.
gc_mut.write_barrier(mutator, |barrier| {
barrier.set(GcMut::new(mutator, false));
})
});
§Collection and Yielding
In order for the Gc to free memory, and do so safely, all mutations must exit. Therefore, if a mutation involves a continuous loop of instructions, it must exit it’s mutation every so often to allow the GC to free memory.
The mutator exposes a signal(Mutator::gc_yield
) which indicates if it is ready to free memory,
and that the mutation should end.
arena.mutate(|mutator, root| loop {
// during this function it is likely the the GC will concurrently begin tracing!
allocate_stuff(mutator, root);
if mutator.gc_yield() {
// the mutator is signaling to us that memory is ready to be freed so we should leave the mutation context
break;
} else {
// if the mutator isn't signaling for us to yield then we
// are fine to go on allocating more garbage
}
});
WARNING: If a mutation continously runs without occasionally checking the yield signal, memory cannot be freed!
Modules§
- gc
- Module containing the three types of GC pointers.
Macros§
- Root
- Re-exported from ForLt. Used in making the root of an arena.
Produce
impl ForLt
types on demand. - field
- Exists to allow getting a write barrier to an inner field.
Structs§
- Arena
- A concurrently garbage collected arena with a single root type.
- Config
- This structure contains the configuration settings for a garbage collector.
- Metrics
- A ‘snapshot’ of the metrics relevant to the GC’s internal triggers.
- Mutator
- Allows for allocation and mutation within the GC arena.
- Write
Barrier - Allows for the mutation of
GcMut
andGcOpt
pointers.
Traits§
- Root
- Re-exported from ForLt. Used in making the root of an arena.
The main trait of the crate. The one expressing
: <'_>
-genericity. - Trace
- Allows tracer to find all GC references stored in a type.
- Trace
Leaf - Indicates a type contains no Gc references internally.