Cycles, Gc as Deref during Drop
ijackson opened this issue · comments
I read your blog post. Cool stuff.
I was curious, so I tried the program below. I didn't expect it to work :-). and indeed it panics, saying "thread 'main' panicked at 'dereferencing GC to already-collected object',".
I think that it would be useful to document that dereferencing a Gc
for a GC'd object can crash. AFAICT this can only occur if a Gc
contained within a T
is accessed in T
's drop
impl. Am I right? (A determined programmer could of course, having gained access to a "bad" Gc
in a drop
impl, break things elsewhere by feeding them the bad Gc
.)
Also, maybe some people doing funky stuff during drop
would want a try deref method. I suggest impl Gc<T> { fn try_deref(this: &Self) -> Option<&T>
use std::cell::RefCell;
use dumpster::{Collectable, unsync::Gc};
#[derive(Collectable, Debug)]
struct Loopy {
value: u32,
loopy: RefCell<Option<Gc<Loopy>>>,
}
impl Drop for Loopy {
fn drop(&mut self) {
eprintln!(
"drop {:?} {:?}",
self.value,
self.loopy.borrow().as_ref().map(|gcl| gcl.value),
);
}
}
fn main() {
let a = Gc::new(Loopy {
value: 42,
loopy: None.into(),
});
let b = Gc::new(Loopy {
value: 66,
loopy: None.into(),
});
*a.loopy.borrow_mut() = Some(b.clone());
*b.loopy.borrow_mut() = Some(a.clone());
drop(a);
drop(b);
eprintln!("returning from main");
}
I believe you're correct - dead Gc
s can only be created by attempting to access a Gc
during its Drop
impl. I'll likely rewrite the code for handling dead Gc
s in the near future.
Thanks for the recommendation on try_deref
. I'll include it in the next release.
I just finished implementing try_deref
and try_clone
on both Gc
s. Feel free to take a look. I'll publish this version soon(ish), whenever I feel like I've ironed out everything.
Looks good to me!
I had one observation: should Clone
on a dead Gc
give you another dead Gc
instead? Having Clone
panic seems rather poor b- ut on the other hand propagating the explosive Gc
seems worse. So my feeling is that you've done it the best way but I thought I'd mention it.