|
1 | 1 | # libgc
|
2 | 2 |
|
3 |
| -libgc is a garbage collector for Rust. It works by providing a garbage-collected |
4 |
| -`Gc<T>` smart pointer in the style of `Rc<T>`. |
| 3 | +[](https://bors.tech) |
5 | 4 |
|
6 |
| -# Structure |
| 5 | +_libgc_ is a garbage collection library for Rust. It can be used as a standalone |
| 6 | +library, but it is highly recommended that programs are compiled with the |
| 7 | +companion [rustc fork](https://github.com/softdevteam/rustgc), which offers |
| 8 | +language support for much better performance. |
| 9 | + |
| 10 | +_libgc_ is in active development - there will be bugs! |
| 11 | + |
| 12 | +## Example |
| 13 | + |
| 14 | +_libgc_ provides a smart pointer, `Gc<T>`, which can be used to make garbage |
| 15 | +collected values. An example, with the necessary global allocator setup, looks |
| 16 | +as follows: |
| 17 | + |
| 18 | +```rust |
| 19 | +use libgc::{Gc, GcAllocator}; |
| 20 | + |
| 21 | +#[global_allocator] |
| 22 | +static ALLOCATOR: GcAllocator = GcAllocator; |
| 23 | + |
| 24 | + |
| 25 | +fn foo() -> Gc<Vec<usize>> { |
| 26 | + let foo = Gc::new(vec![1,2,3]); |
| 27 | + let a = foo; // GC pointers are copyable |
| 28 | + let b = foo; |
| 29 | + |
| 30 | + foo |
| 31 | +} |
| 32 | + |
| 33 | +fn main() { |
| 34 | + let gc = foo(); |
| 35 | +} |
| 36 | +``` |
| 37 | + |
| 38 | +## Overview |
| 39 | + |
| 40 | +If you want to write code with shared ownership in Rust, `Rc` makes this |
| 41 | +possible. Unfortunately, managing cyclic data structures with reference counting |
| 42 | +is hard: weak pointers are needed to break strong cycles and thus prevent memory |
| 43 | +leaks. In programs where these sorts of structures are common, |
| 44 | +garbage collection is a natural fit. |
| 45 | + |
| 46 | +_libgc_ is not a replacement to the single ownership model - it is intended to |
| 47 | +complement it by providing a garbage collected alternative for values which |
| 48 | +might be too difficult to manage with `Rc`. Values must opt-in to using |
| 49 | +garbage collection with the `Gc::new(x)` constructor. This tells _libgc_ to heap |
| 50 | +allocate `x`, and GC it for you when you're done with it. `Gc` can be thought of |
| 51 | +as a special `Box` type, where `x`'s lifetime is unknown at compile-time. |
| 52 | +Periodically, the garbage collector will interrupt the program (known as |
| 53 | +"stopping the world") to see which `Gc` values are still in use, and drop those |
| 54 | +which aren't. |
| 55 | + |
| 56 | +Garbage collection involves scanning parts of the stack and heap to look for |
| 57 | +live references to `Gc` values. This means that _libgc_ must be aware of all heap |
| 58 | +allocated values, even those which aren't `Gc`. To do this, _libgc_ has its own |
| 59 | +allocator, `GcAllocator`, which must be set as the global allocator when using |
| 60 | +_libgc_. |
| 61 | + |
| 62 | +```rust |
| 63 | +use libgc::GcAllocator; |
| 64 | + |
| 65 | +#[global_allocator] |
| 66 | +static ALLOCATOR: GcAllocator = GcAllocator; |
| 67 | +``` |
| 68 | + |
| 69 | +### Finalization |
| 70 | + |
| 71 | +A `Gc` can be used to manage values which have a `drop` method. Like all tracing |
| 72 | +garbage collectors, _libgc_ can not provide any guarantees about exactly when a |
| 73 | +'dead' value is dropped. Instead, once _libgc_ has determined that a value is |
| 74 | +unreachable, its `drop` method is added to a drop queue, which is ran on a |
| 75 | +parallel finalization thread at some point in the future. The order of |
| 76 | +finalization is intentionally undefined to allow _libgc_ to run `drop` methods on |
| 77 | +values which contain cycles of `Gc`. |
| 78 | + |
| 79 | +:warning: You must not dereference a field of type `Gc<T>` inside `Drop::drop`. |
| 80 | +Doing so is unsound and can lead to dangling pointers. TODO: Add a lint for this |
| 81 | +and explain why in further details. |
| 82 | + |
| 83 | +## Implementation |
| 84 | + |
| 85 | +__libgc__ is implemented using the [Boehm-Demers-Weiser |
| 86 | +collector](https://github.com/https://github.com/ivmai/bdwgc). It is a |
| 87 | +conservative, stop-the-world, parallel, mark-sweep collector. |
| 88 | + |
| 89 | +TODO: Expand |
| 90 | + |
| 91 | +## Known Issues |
| 92 | + |
| 93 | +* Single-threaded support only. |
| 94 | +* No Drop Lint to prevent unsound dereferencing of `Gc` typed fields. |
| 95 | + |
| 96 | +## Using libgc with rustgc |
7 | 97 |
|
8 | 98 | There are two repositories which make up the gc infrastructure:
|
9 | 99 |
|
10 | 100 | * **libgc** the main library which provides the `Gc<T>` smart pointer and its
|
11 | 101 | API.
|
12 | 102 | * **rustgc** a fork of rustc with GC-aware optimisations. This can be used to
|
13 |
| - compile user programs which use `libgc`, giving them better GC |
| 103 | + compile user programs which use libgc, giving them better GC |
14 | 104 | performance. Use of rustgc is not mandated, but it enables further
|
15 |
| - optimisations for programs which use `libgc`. |
| 105 | + optimisations for programs which use libgc. |
16 | 106 |
|
17 | 107 | This seperation between libgc and rustgc exists so that a stripped-down form of
|
18 | 108 | garbage collection can be used without compiler support.
|
| 109 | + |
| 110 | +TODO: Explain rustgc and it's optimizations. |
0 commit comments