https://github.com/fitzgen/safe-gc
A garbage collection library for Rust with zero unsafe code
https://github.com/fitzgen/safe-gc
Last synced: about 1 year ago
JSON representation
A garbage collection library for Rust with zero unsafe code
- Host: GitHub
- URL: https://github.com/fitzgen/safe-gc
- Owner: fitzgen
- License: apache-2.0
- Created: 2024-01-31T07:24:35.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-07-15T22:07:56.000Z (almost 2 years ago)
- Last Synced: 2025-04-09T18:18:48.371Z (about 1 year ago)
- Language: Rust
- Homepage: https://docs.rs/safe-gc
- Size: 43.9 KB
- Stars: 111
- Watchers: 4
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
## About
`safe-gc` implements a garbage collection library for Rust with zero `unsafe`
code and zero dependencies. It even has a `forbid(unsafe_code)` directive at the
top!
Additional features:
* Allows constructing and collecting arbitrary heap graphs, including cycles. It
doesn't impose any ownership hierarchy, or anything like that, to the shapes
of references between GC-managed objects within the heap.
* Leverages Rust's ownership and borrowing in its API: if you have an `&mut
Heap`, you can get mutable access to objects in the heap. It doesn't, for
example, force everything in the heap into `RefCell`s, or only give out shared
references to GC-managed objects, or similar.
* Allows constructing multiple, separate GC heaps that can be independently
collected.
* Allows allocating any number of heterogeneous types within the heap. For
example, you can allocate both `Cons` and `Tree` objects within the
heap. Heaps are *not* constrained to only a single, uniform `T` type of GC
objects.
* Footgun-free GC object finalization with Rust's regular, old `Drop` trait. No
worries about accidentally deref'ing pointers to GC objects the collector has
already reclaimed or resurrecting objects it was about to reclaim.
`safe-gc` is not, however, a particularly high-performance garbage collector.
## Usage
* Define types managed by the GC.
* Define references from within one GC type to another GC type with `Gc`.
* Implement `Trace` for your GC-managed types.
* Create one or more `Heap`s.
* Allocate objects in your `Heap`s.
* Hold onto GC roots with `Root`.
* Let the garbage collector reclaim unreachable objects!
## Example
```rust
use safe_gc::{Collector, Gc, Heap, Trace};
// Define a GC-managed tree of `T` values.
struct Tree {
value: Gc,
// A cyclic parent pointer.
parent: Option>>,
// Left and right subtrees.
left: Option>>,
right: Option>>,
}
// Report each of the GC references within a `Tree` to the
// collector.
//
// See the `Trace` docs for more details.
impl Trace for Tree {
fn trace(&self, collector: &mut Collector) {
collector.edge(self.value);
if let Some(parent) = self.parent {
collector.edge(parent);
}
if let Some(left) = self.left {
collector.edge(left);
}
if let Some(right) = self.right {
collector.edge(right);
}
}
}
// Another GC type!
struct Cat {
cuteness: u32,
cat_tree: Option>>,
}
impl Trace for Cat {
fn trace(&self, collector: &mut Collector) {
if let Some(tree) = self.cat_tree {
collector.edge(tree);
}
}
}
// Create a new GC heap!
let mut heap = Heap::new();
// Allocate some objects in the heap!
let momo = heap.alloc(Cat {
cuteness: u32::MAX,
cat_tree: None,
});
let tree = heap.alloc(Tree {
value: momo.unrooted(),
parent: None,
left: None,
right: None,
});
// Create a bunch of garbage! Who cares!
for _ in 0..100 {
let _ = heap.alloc(Tree {
value: momo.unrooted(),
parent: None,
left: None,
right: None,
});
}
// Read data from objects in the heap!
let cuteness = heap[&momo].cuteness;
assert_eq!(cuteness, u32::MAX);
// Mutate objects in the heap!
heap[&momo].cat_tree = Some(tree.into());
// Garbage collections will happen automatically, as necessary, but you can also
// force a collection, if you want!
heap.gc();
```
## Why?
`safe-gc` is certainly a point in the design space of garbage-collection
libraries in Rust. One could even argue it is an interesting -- and maybe even
useful? -- point in the design space!
Also, it was fun!
At the very least, you don't have to wonder about the correctness of any
`unsafe` code in here, because there isn't any. As long as the Rust language and
its standard library are sound, this crate is too.