You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+42-22Lines changed: 42 additions & 22 deletions
Original file line number
Diff line number
Diff line change
@@ -22,34 +22,54 @@ This can be used pretty much like `Rc`, with the exception of interior mutabilit
22
22
23
23
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.
24
24
25
-
Types placed inside a `Gc` must implement `Trace`. The easiest way to do this is to use the `gc_derive` crate:
25
+
Types placed inside a `Gc` must implement `Trace` and `Finalize`. The easiest way to do this is to use the `gc_derive` crate:
26
26
27
27
```rust
28
-
#![feature(proc_macro)]
29
-
30
28
#[macro_use]
31
29
externcrate gc_derive;
32
30
externcrate gc;
33
31
34
32
usegc::Gc;
35
33
36
-
#[derive(Trace)]
34
+
#[derive(Trace, Finalize)]
37
35
structFoo {
38
-
x:Gc<Foo>,
39
-
y:u8,
40
-
// ...
36
+
x:Gc<Foo>,
37
+
y:u8,
38
+
// ...
41
39
}
42
40
43
41
// now, `Gc<Foo>` may be used
44
42
```
45
43
44
+
> NOTE: Finalize is automatically implemented on all types when the `nightly`
45
+
> feature is enabled through specialization.
46
+
47
+
`Finalize` may also be implemented directly on the struct, in order to add custom finalizer behavior:
48
+
49
+
```rust
50
+
#[macro_use]
51
+
externcrate gc_derive;
52
+
externcrate gc;
53
+
54
+
usegc::Finalize;
55
+
56
+
#[derive(Trace)]
57
+
structFoo {...}
58
+
59
+
implFinalizeforFoo {
60
+
fnfinalize(&self) {
61
+
// Clean up resources for Foo, because we think it will be destroyed.
62
+
// Foo may not be destroyed after a call to finalize, as another
63
+
// finalizer may create a reference to it due to reference cycles.
64
+
}
65
+
}
66
+
```
67
+
46
68
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).
47
69
48
70
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.
49
71
50
72
```rust
51
-
#![feature(proc_macro)]
52
-
53
73
#[macro_use]
54
74
externcrate gc_derive;
55
75
externcrate gc;
@@ -59,12 +79,12 @@ extern crate bar;
59
79
usegc::Gc;
60
80
usebar::Baz;
61
81
62
-
#[derive(Trace)]
82
+
#[derive(Trace, Finalize)]
63
83
structFoo {
64
-
x:Gc<Foo>,
65
-
#[unsafe_ignore_trace]
66
-
y:Baz, // we are assuming that `Baz` doesn't contain any `Gc` objects
67
-
// ...
84
+
x:Gc<Foo>,
85
+
#[unsafe_ignore_trace]
86
+
y:Baz, // we are assuming that `Baz` doesn't contain any `Gc` objects
87
+
// ...
68
88
}
69
89
```
70
90
@@ -74,10 +94,10 @@ To use `Gc`, simply call `Gc::new`:
74
94
letx=Gc::new(1_u8);
75
95
lety=Gc::new(Box::new(Gc::new(1_u8)));
76
96
77
-
#[derive(Trace)]
97
+
#[derive(Trace, Finalize)]
78
98
structFoo {
79
-
a:Gc<u8>,
80
-
b:u8
99
+
a:Gc<u8>,
100
+
b:u8
81
101
}
82
102
83
103
letz=Gc::new(Foo {a:x.clone(), b:1})
@@ -88,10 +108,10 @@ Calling `clone()` on a `Gc` will create another garbage collected reference to t
88
108
`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.
- Destructors should not access `Gc`/`GcCell` values. We may add finalizers in the future, but we'd need to figure out a way to prevent this.
107
-
- There needs to be a better story for cross-crate deriving, but we may have to wait for the middle IR to land to work on this.
126
+
- 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.
127
+
- There needs to be a better story for cross-crate deriving.
108
128
- 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](https://github.com/Manishearth/rust-gc/pull/6).
0 commit comments