[oden] The big lifetime removal
It turns out that rust can't really reason about the relationship between the runtime lifetime and the context lifetime in a way that is actually usable. This removes the lifetime stuff in favor of reference counting the runtime itself, via a block that we embed in the pointer. This, I think, it the least worst option here.
This commit is contained in:
parent
898b1fe129
commit
9f808cea31
10 changed files with 269 additions and 312 deletions
|
|
@ -1,4 +1,9 @@
|
|||
use oden_js_sys as sys;
|
||||
use std::cell::RefCell;
|
||||
|
||||
struct PrivateState {
|
||||
refs: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Runtime {
|
||||
|
|
@ -7,7 +12,23 @@ pub struct Runtime {
|
|||
|
||||
impl Runtime {
|
||||
pub fn new() -> Runtime {
|
||||
let rt = unsafe { sys::JS_NewRuntime() };
|
||||
let state = Box::new(RefCell::new(PrivateState { refs: 1 }));
|
||||
let rt = unsafe {
|
||||
let rt = sys::JS_NewRuntime();
|
||||
sys::JS_SetRuntimeOpaque(rt, Box::into_raw(state) as *mut _);
|
||||
rt
|
||||
};
|
||||
Runtime { rt }
|
||||
}
|
||||
|
||||
pub(crate) fn from_raw(rt: *mut sys::JSRuntime) -> Self {
|
||||
let mut state = unsafe {
|
||||
let ptr = sys::JS_GetRuntimeOpaque(rt) as *const RefCell<PrivateState>;
|
||||
ptr.as_ref()
|
||||
.expect("We already know this runtime is one of ours!")
|
||||
.borrow_mut()
|
||||
};
|
||||
state.refs += 1;
|
||||
Runtime { rt }
|
||||
}
|
||||
|
||||
|
|
@ -37,11 +58,36 @@ impl Runtime {
|
|||
}
|
||||
}
|
||||
|
||||
impl Clone for Runtime {
|
||||
fn clone(&self) -> Self {
|
||||
Runtime::from_raw(self.rt)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Runtime {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
sys::JS_RunGC(self.rt);
|
||||
sys::JS_FreeRuntime(self.rt);
|
||||
let should_free = {
|
||||
let mut state = unsafe {
|
||||
let ptr = sys::JS_GetRuntimeOpaque(self.rt) as *const RefCell<PrivateState>;
|
||||
ptr.as_ref()
|
||||
.expect("We already know this runtime is one of ours!")
|
||||
.borrow_mut()
|
||||
};
|
||||
state.refs -= 1;
|
||||
state.refs == 0
|
||||
};
|
||||
|
||||
if should_free {
|
||||
unsafe {
|
||||
let opaque = sys::JS_GetRuntimeOpaque(self.rt);
|
||||
sys::JS_RunGC(self.rt);
|
||||
sys::JS_FreeRuntime(self.rt);
|
||||
|
||||
if !opaque.is_null() {
|
||||
// Just let the system drop it here.
|
||||
let _ = Box::from_raw(opaque as *mut RefCell<PrivateState>);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue