fix(napi): thread safe issue while creating class instance ()

This commit is contained in:
LongYinan 2023-04-15 15:37:01 +08:00 committed by GitHub
parent 77f53a8cc9
commit d14fdca242
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 19 deletions
crates/napi/src/bindgen_runtime

View file

@ -1,14 +1,10 @@
use std::cell::Cell;
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::ffi::c_void;
use std::ops::{Deref, DerefMut};
use std::rc::{Rc, Weak};
use once_cell::sync::Lazy;
use crate::{
bindgen_runtime::{PersistedPerInstanceHashMap, ToNapiValue},
check_status, Env, Error, Result, Status,
};
use crate::{bindgen_runtime::ToNapiValue, check_status, Env, Error, Result, Status};
type RefInformation = (
*mut c_void,
@ -16,8 +12,9 @@ type RefInformation = (
*const Cell<*mut dyn FnOnce()>,
);
pub(crate) static REFERENCE_MAP: Lazy<PersistedPerInstanceHashMap<*mut c_void, RefInformation>> =
Lazy::new(Default::default);
thread_local! {
pub(crate) static REFERENCE_MAP: RefCell<HashMap<*mut c_void, RefInformation>> = RefCell::new(HashMap::default());
}
/// ### Experimental feature
///
@ -61,8 +58,8 @@ impl<T: 'static> Reference<T> {
#[doc(hidden)]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn add_ref(env: crate::sys::napi_env, t: *mut c_void, value: RefInformation) {
REFERENCE_MAP.borrow_mut(|map| {
if let Some((_, previous_ref, previous_rc)) = map.insert(t, value) {
REFERENCE_MAP.with(|map| {
if let Some((_, previous_ref, previous_rc)) = map.borrow_mut().insert(t, value) {
unsafe { Rc::from_raw(previous_rc) };
unsafe { crate::sys::napi_delete_reference(env, previous_ref) };
}
@ -72,7 +69,7 @@ impl<T: 'static> Reference<T> {
#[doc(hidden)]
pub unsafe fn from_value_ptr(t: *mut c_void, env: crate::sys::napi_env) -> Result<Self> {
if let Some((wrapped_value, napi_ref, finalize_callbacks_ptr)) =
REFERENCE_MAP.borrow_mut(|map| map.get(&t).cloned())
REFERENCE_MAP.with(|map| map.borrow().get(&t).cloned())
{
check_status!(
unsafe { crate::sys::napi_reference_ref(env, napi_ref, &mut 0) },

View file

@ -40,7 +40,7 @@ pub unsafe extern "C" fn raw_finalize_unchecked<T: ObjectFinalize>(
unsafe { e.throw_into(env) };
}
if let Some((_, ref_val, finalize_callbacks_ptr)) =
REFERENCE_MAP.borrow_mut(|reference_map| reference_map.remove(&finalize_data))
REFERENCE_MAP.with(|reference_map| reference_map.borrow_mut().remove(&finalize_data))
{
let finalize_callbacks_rc = unsafe { Rc::from_raw(finalize_callbacks_ptr) };