Skip to content

Commit

Permalink
Move class list to opaque
Browse files Browse the repository at this point in the history
  • Loading branch information
richarddavison committed Oct 10, 2024
1 parent 9e46321 commit 909d347
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 26 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,9 @@ jobs:
overwrite: true
- name: Build
if: ${{ !matrix.no-build }}
run: cargo build ${{ matrix.optimization && '--release' || '' }} --target ${{ matrix.target }} --no-default-features --features ${{ matrix.features }}
run: |
cargo clean
cargo build ${{ matrix.optimization && '--release' || '' }} --target ${{ matrix.target }} --no-default-features --features ${{ matrix.features }}
- name: Test
if: ${{ !matrix.no-build && !matrix.no-test }}
timeout-minutes: 12
Expand Down
35 changes: 11 additions & 24 deletions core/src/class/id.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
use rquickjs_sys::JSRuntime;

use crate::qjs;
use std::{
collections::HashMap,
sync::{
atomic::{AtomicUsize, Ordering},
OnceLock, RwLock,
},
use crate::{
qjs,
runtime::opaque::{ClassIdKey, Opaque},
};
use std::sync::atomic::{AtomicUsize, Ordering};

/// The type of identifier of class
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "classes")))]
pub struct ClassId {
type_id: AtomicUsize,
}

#[derive(Eq, Hash, PartialEq)]
struct ClassIdKey(*mut JSRuntime, usize);

unsafe impl Sync for ClassIdKey {}
unsafe impl Send for ClassIdKey {}

static CLASS_ID_COUNTER: AtomicUsize = AtomicUsize::new(1);
static CLASS_ID_MAP: OnceLock<RwLock<HashMap<ClassIdKey, qjs::JSClassID>>> = OnceLock::new();

impl ClassId {
/// Create a new class id.
Expand All @@ -39,18 +29,15 @@ impl ClassId {
pub fn get(&self, rt: *mut JSRuntime) -> qjs::JSClassID {
let type_id = self.init_type_id();
let key = ClassIdKey(rt, type_id);
let class_id_lock = CLASS_ID_MAP.get_or_init(|| RwLock::new(HashMap::new()));
if let Some(class_id) = class_id_lock.read().unwrap().get(&key) {
return *class_id;
}

let mut read_lock = class_id_lock.write().unwrap();
let mut id = 0;
unsafe { qjs::JS_NewClassID(rt, &mut id) };
let opaque = unsafe { &(*qjs::JS_GetRuntimeOpaque(rt).cast::<Opaque>()) };

read_lock.insert(key, id);

id
let id = opaque.get_class_id_map().entry(key).or_insert_with(|| {
let mut id = 0;
unsafe { qjs::JS_NewClassID(rt, &mut id) };
id
});
*id
}

/// Initialize the class ID.
Expand Down
16 changes: 16 additions & 0 deletions core/src/runtime/opaque.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use rquickjs_sys::JSRuntime;

use crate::qjs;

use super::{
userdata::{UserDataGuard, UserDataMap},
InterruptHandler, UserData, UserDataError,
};
use std::{
any::Any,
cell::{Cell, UnsafeCell},
collections::HashMap,
marker::PhantomData,
};

Expand All @@ -17,6 +22,9 @@ use std::{
task::{Context, Waker},
};

#[derive(Eq, Hash, PartialEq)]
pub struct ClassIdKey(pub *mut JSRuntime, pub usize);

/// Opaque book keeping data for Rust.
pub(crate) struct Opaque<'js> {
/// Used to carry a panic if a callback triggered one.
Expand All @@ -25,6 +33,8 @@ pub(crate) struct Opaque<'js> {
/// The user provided interrupt handler, if any.
interrupt_handler: UnsafeCell<Option<InterruptHandler>>,

class_id_map: UnsafeCell<HashMap<ClassIdKey, qjs::JSClassID>>,

userdata: UserDataMap,

#[cfg(feature = "futures")]
Expand All @@ -38,6 +48,7 @@ impl<'js> Opaque<'js> {
Opaque {
panic: Cell::new(None),
interrupt_handler: UnsafeCell::new(None),
class_id_map: UnsafeCell::new(HashMap::new()),
userdata: UserDataMap::default(),
#[cfg(feature = "futures")]
spawner: None,
Expand All @@ -50,6 +61,7 @@ impl<'js> Opaque<'js> {
Opaque {
panic: Cell::new(None),
interrupt_handler: UnsafeCell::new(None),
class_id_map: UnsafeCell::new(HashMap::new()),
userdata: UserDataMap::default(),
#[cfg(feature = "futures")]
spawner: Some(UnsafeCell::new(Spawner::new())),
Expand Down Expand Up @@ -120,4 +132,8 @@ impl<'js> Opaque<'js> {
pub fn take_panic(&self) -> Option<Box<dyn Any + Send + 'static>> {
self.panic.take()
}

pub(crate) fn get_class_id_map(&self) -> &mut HashMap<ClassIdKey, u32> {
unsafe { &mut *self.class_id_map.get() }
}
}
2 changes: 1 addition & 1 deletion core/src/runtime/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ impl Drop for RawRuntime {
unsafe {
let ptr = qjs::JS_GetRuntimeOpaque(self.rt.as_ptr());
let opaque: Box<Opaque> = Box::from_raw(ptr as *mut _);
qjs::JS_FreeRuntime(self.rt.as_ptr());
mem::drop(opaque);
qjs::JS_FreeRuntime(self.rt.as_ptr())
}
}
}
Expand Down

0 comments on commit 909d347

Please sign in to comment.