Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save federicomenaquintero/086b0335847ec884038694892f6192d7 to your computer and use it in GitHub Desktop.
Save federicomenaquintero/086b0335847ec884038694892f6192d7 to your computer and use it in GitHub Desktop.
pub struct Node {
...
}
pub type RsvgNode = Weak<Node>;
/* This one works */
#[no_mangle]
pub unsafe extern fn rsvg_node_ref (raw_node: *mut RsvgNode) -> *const RsvgNode {
assert! (!raw_node.is_null ());
let weak_node: &RsvgNode = & *raw_node;
let node = weak_node.upgrade ().unwrap ();
mem::forget (node.clone ());
raw_node
}
/* This one doesn't work; doesn't remove a reference at all */
#[no_mangle]
pub extern fn rsvg_node_unref (raw_node: *mut RsvgNode) {
assert! (!raw_node.is_null ());
let weak_node: &RsvgNode = unsafe { &*raw_node };
let node = weak_node.upgrade ().unwrap ();
println! ("before unref: {}", Rc::strong_count (&node));
mem::drop (node);
if weak_node.upgrade ().is_none () {
let _ = unsafe { Box::from_raw (raw_node) };
println! ("dropping");
} else {
println! ("not dropping");
}
}
#[test]
fn node_refs_and_unrefs () {
let node = Rc::new (Node::new (...));
let node_ptr = Box::into_raw (Box::new (Rc::downgrade (&node)));
let weak_node: &RsvgNode = unsafe { &*node_ptr };
unsafe { rsvg_node_ref (node_ptr); }
assert_eq! (Rc::strong_count (&node), 2);
unsafe { rsvg_node_unref (node_ptr); }
assert_eq! (Rc::strong_count (&node), 1); // <------ This assertion fails; 2 != 1
unsafe { rsvg_node_unref (node_ptr); }
assert! (weak_node.upgrade ().is_none ());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment