Use Box instead of NonNull to clarify ownership of the list of allocations#107
Use Box instead of NonNull to clarify ownership of the list of allocations#107calebsander wants to merge 1 commit intoManishearth:masterfrom
Conversation
The second use gc::{force_collect, Finalize, Gc, GcCell, Trace};
#[derive(Finalize, Trace)]
struct Foo {
bar: GcCell<Option<Gc<Bar>>>,
}
#[derive(Trace)]
struct Bar {
n: u32,
foo: Gc<Foo>,
this: GcCell<Option<Gc<Bar>>>,
}
impl Finalize for Bar {
fn finalize(&self) {
println!("finalizing Bar {}", self.n);
*self.foo.bar.borrow_mut() = self.this.borrow().clone();
}
}
fn main() {
let foo = Gc::new(Foo {
bar: GcCell::new(None),
});
let bar = Gc::new(Bar {
n: 17,
foo: foo.clone(),
this: GcCell::new(None),
});
*bar.this.borrow_mut() = Some(bar.clone());
drop(bar);
force_collect();
println!(
"Bar {} is still reachable",
foo.bar.borrow().as_ref().unwrap().n
);
}
You’re right, and this is a bug. It appears the intention was to skip the deallocation of nodes that were marked in the second pass, for the above reason—but the needed Filed as #124.
The current code needs the backwards iteration so that the cached |
|
Hmmm, so I'm unsure about this: AIUI it is within the scope of Rust's unsafe guidelines for accessing |
This made it possible to remove several sections of
unsafecode. I also eliminated the temporaryVecused to store the unmarked nodes; instead, they are stored in a linked list built from theGcBox.header.nextpointers.There were a few additional things I removed from the mark-and-sweep code, but I wasn't sure why they were there in the first place:
mark()pass after finalizing all the unmarked objects. I can't see how the set of marked objects would change after the first pass, and if they do, then the new garbage nodes are ignored anyways. It seems quite expensive anyways to traverse the reference graph twice.falsesince all nodes are unmarked whenmark()finishes.