• Stars
    star
    862
  • Rank 52,908 (Top 2 %)
  • Language
    Rust
  • License
    Mozilla Public Li...
  • Created over 9 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Simple tracing (mark and sweep) garbage collector for Rust

rust-gc

Build Status

Simple tracing (mark and sweep) garbage collector for Rust

The design and motivation is illustrated in this blog post, with a sketch of the code in this gist.

There is another post about the initial design of cgc, its experimental concurrent branch.

How to use

To include in your project, add the following to your Cargo.toml:

[dependencies]
gc = { version = "0.4", features = ["derive"] }

This can be used pretty much like Rc, with the exception of interior mutability.

While this can be used pervasively, this is intended to be used only when needed, following Rust's "pay only for what you need" model. Avoid using Gc where Rc or Box would be equally usable.

Types placed inside a Gc must implement Trace and Finalize. The easiest way to do this is to use the gc_derive crate:

use gc::{Finalize, Gc, Trace};

#[derive(Trace, Finalize)]
struct Foo {
    x: Option<Gc<Foo>>,
    y: u8,
    // ...
}

// now, `Gc<Foo>` may be used

Finalize may also be implemented directly on the struct, in order to add custom finalizer behavior:

use gc::{Finalize, Trace};

#[derive(Trace)]
struct Foo {...}

impl Finalize for Foo {
    fn finalize(&self) {
        // Clean up resources for Foo, because we think it will be destroyed.
        // Foo may not be destroyed after a call to finalize, as another
        // finalizer may create a reference to it due to reference cycles.
    }
}

For types defined in the stdlib, please file an issue on this repository (use the unsafe_ignore_trace method shown below to make things work in the meantime).

Note that Trace is only needed for types which transitively contain a Gc, if you are sure that this isn't the case, you may use the unsafe_empty_trace! macro on your types. Alternatively, use the #[unsafe_ignore_trace] annotation on the struct field. Incorrect usage of unsafe_empty_trace and unsafe_ignore_trace may lead to unsafety.

use gc::{Finalize, Gc, Trace};
use bar::Baz;

#[derive(Trace, Finalize)]
struct Foo {
    x: Option<Gc<Foo>>,
    #[unsafe_ignore_trace]
    y: Baz, // we are assuming that `Baz` doesn't contain any `Gc` objects
    // ...
}

To use Gc, simply call Gc::new:

let x = Gc::new(1_u8);
let y = Gc::new(Box::new(Gc::new(1_u8)));

#[derive(Trace, Finalize)]
struct Foo {
    a: Gc<u8>,
    b: u8
}

let z = Gc::new(Foo {a: x.clone(), b: 1})

Calling clone() on a Gc will create another garbage collected reference to the same object. For the most part, try to use borrowed references to the inner value instead of cloning the Gc wherever possible -- Gc implements Deref and is compatible with borrowing.

Gc is an immutable container. Much like with Rc, to get mutability, we must use a cell type. The regular RefCell from the stdlib will not work with Gc (as it does not implement Trace), instead, use GcCell. GcCell behaves very similar to RefCell, except that it internally helps keep track of GC roots.

#[derive(Trace, Finalize)]
struct Foo {
    cyclic: GcCell<Option<Gc<Foo>>>,
    data: u8,
}

let foo1 = Gc::new(Foo {cyclic: GcCell::new(None), data: 1});
let foo2 = Gc::new(Foo {cyclic: GcCell::new(Some(foo1.clone())), data: 2});
let foo3 = Gc::new(Foo {cyclic: GcCell::new(Some(foo2.clone())), data: 3});
*foo1.cyclic.borrow_mut() = Some(foo3.clone());

Known issues

  • Destructors should not access Gc/GcCell values. This is enforced by the Trace custom derive automatically implementing Drop with a safe empty drop method. Finalize should be used for cleanup instead.
  • There needs to be a better story for cross-crate deriving.
  • The current GC is not concurrent and the GCed objects are confined to a thread. There is an experimental concurrent collector in this pull request.

Related projects

  • RuScript: Uses single-thread rust-gc to allocate memory for various objects

More Repositories

1

compiletest-rs

An extraction of the compiletest utility from the Rust compiler
Rust
216
star
2

elsa

Append-only collections for Rust where borrows to entries can outlive insertions
Rust
171
star
3

triomphe

Fork of std::sync::Arc with lots of utilities useful for FFI
Rust
154
star
4

rust-adorn

Python-style function decorators for Rust
Rust
153
star
5

absolution

"Freedom from syn": Proc macro tools for operating on token trees
Rust
107
star
6

mitosis

Spawn processes with arbitrary closures in rust
Rust
105
star
7

oreutils

Installer for various Rust reimaginations of coreutils. These are not drop-in replacements.
Rust
93
star
8

array-init

Safe wrapper for initializing arrays
Rust
67
star
9

ChatExchange

A Python API for talking to Stack Exchange chat
Python
65
star
10

namespacing-rfc

RFC for Packages as Optional Namespaces
46
star
11

rust-tenacious

Lint to disallow the moving of marked types in Rust
Rust
34
star
12

pathdiff

Rust
28
star
13

cs733

CS 733 assignments
Go
25
star
14

rust-internals-docs

Deprecated, please use the official docs at https://doc.rust-lang.org/nightly/nightly-rustc
HTML
24
star
15

IIT-Timetable

Timetable generator for IIT Bombay
HTML
14
star
16

humpty_dumpty

Implicit Drop/move protection for Rust (linear types)
Rust
12
star
17

AnnoTabe

Annotations for tabs in Chrome
JavaScript
11
star
18

dash

Distributed Shell: A way to replicate system administration commands across machines using Raft
Go
10
star
19

handlebars-fluent

Rust
10
star
20

webgl-to-webvr

Example of turning a WebGL application into WebVR
JavaScript
8
star
21

Manish-Codes

JavaScript
8
star
22

manishearth.github.io

HTML
5
star
23

webgl-to-webxr

Webxr version of https://github.com/Manishearth/webgl-to-webvr
JavaScript
5
star
24

error-index-localization

Rust error index localization
Rust
4
star
25

trashmap

A HashMap and HashSet that operate directly on hashes instead of keys, avoiding rehashing
Rust
4
star
26

rust-extensible

Extensible enums for Rust
Rust
4
star
27

hashglobe

A stable fork of std::HashMap with fallible APIs. Untested.
Rust
3
star
28

reiterate

Iterator adaptor with caching that allows reiterating over the same iterator through the cache
Rust
3
star
29

sudoku-zkp

JavaScript
2
star
30

media-capture

playing around with gstreamer media capture (temporary repo)
Rust
2
star
31

typing-cheatsheets

Cheatsheets for various keyboards
HTML
2
star
32

HostelNoticeboard

Electronic noticeboard for IIT Bombay hostels. Meant to run on an Raspberry Pi.
PHP
2
star
33

sudoku

sudoku annotation/solving tool
JavaScript
2
star
34

webxr-three

three.js fork for webxr testing stuff.
JavaScript
2
star
35

Kapi

Math notebook for Windows 8 Metro
JavaScript
2
star
36

freestring

CString, but with malloc and free
Rust
2
star
37

MathToTeX

JavaScript
2
star
38

css-properties-list

HTML
2
star
39

testcrate

Rust
1
star
40

gstreamer-presentation

JavaScript
1
star
41

rustconf-2017

Website for RustConf 2017
CSS
1
star
42

ChatExchange-Scripts

Scripts that use ChatExchange
Python
1
star
43

ElectionPortal

The worst PHP code I have ever written. Hey, I was in a hurry.
CSS
1
star
44

stylo-flat

Copy of http://hg.mozilla.org/incubator/stylo with history removed for easy cloning and contribution
1
star
45

servo-gecko-try

Service for forwarding servo PRs to gecko's try infra
Python
1
star
46

iterm-git-add-hunk

lol
Shell
1
star
47

StackExchange-ChatBot

Generic Stack Exchange chatbot, using ChatExchange
Python
1
star
48

Presentations

Slides and presentations
JavaScript
1
star
49

rustfest-slides

Slides for my RustFest 2017 (Kiev) keynote
JavaScript
1
star
50

starcon-presentation

JavaScript
1
star
51

bell-inequality-paper

Term paper on Bell's inequality
TeX
1
star