Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Simple tracing (mark and sweep) garbage collector for Rust

License

NotificationsYou must be signed in to change notification settings

Manishearth/rust-gc

Repository files navigation

Build Status

Simple tracing (mark and sweep) garbage collector for Rust

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

There isanother post about the initial design ofcgc, its experimental concurrent branch.

How to use

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

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

This can be used pretty much likeRc, 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 usingGc whereRc orBox would be equally usable.

Types placed inside aGc must implementTrace andFinalize. The easiest way to do this is to use thegc_derive crate:

use gc::{Finalize,Gc,Trace};#[derive(Trace,Finalize)]structFoo{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)]structFoo{...}implFinalizeforFoo{fnfinalize(&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.// Recursive calls of Finalize::finalize on fields are not required here// because this is handled by Trace::finalize_glue already.}}

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

Note thatTrace is only needed for types which transitively contain aGc, if you are sure that this isn't the case, you may use theunsafe_empty_trace! macro on your types. Alternatively, use the#[unsafe_ignore_trace] annotation on the struct field. Incorrect usage ofunsafe_empty_trace andunsafe_ignore_trace may lead to unsafety.

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

To useGc, simply callGc::new:

let x =Gc::new(1_u8);let y =Gc::new(Box::new(Gc::new(1_u8)));#[derive(Trace,Finalize)]structFoo{a:Gc<u8>,b:u8}let z =Gc::new(Foo{a: x.clone(),b:1})

Callingclone() on aGc 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 theGc wherever possible --Gc implementsDeref and is compatible with borrowing.

Gc is an immutable container. Much like withRc, to get mutability, we must use a cell type. The regularRefCell from the stdlib will not work withGc (as it does not implementTrace), instead, useGcCell.GcCell behaves very similar toRefCell, except that it internally helps keep track of GC roots.

#[derive(Trace,Finalize)]structFoo{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 accessGc/GcCell values. This is enforced by theTrace custom derive automatically implementingDrop 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 collectorin this pull request.

Related projects

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

About

Simple tracing (mark and sweep) garbage collector for Rust

Resources

License

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp