From c01bcecb2b053dc155138d70746ac9c091b788c4 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 16 Dec 2022 14:32:01 +0800 Subject: [PATCH] chore(napi): reduce the complex about destroying tokio runtime --- .../src/bindgen_runtime/module_register.rs | 19 +------- crates/napi/src/tokio_runtime.rs | 44 +++---------------- examples/napi/__test__/unload.spec.js | 11 +++++ 3 files changed, 19 insertions(+), 55 deletions(-) create mode 100644 examples/napi/__test__/unload.spec.js diff --git a/crates/napi/src/bindgen_runtime/module_register.rs b/crates/napi/src/bindgen_runtime/module_register.rs index a39212f8..41388fe3 100644 --- a/crates/napi/src/bindgen_runtime/module_register.rs +++ b/crates/napi/src/bindgen_runtime/module_register.rs @@ -1,5 +1,5 @@ use std::collections::{HashMap, HashSet}; -use std::ffi::{c_void, CStr}; +use std::ffi::CStr; use std::ptr; use std::sync::atomic::AtomicUsize; use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; @@ -473,27 +473,10 @@ unsafe extern "C" fn napi_register_module_v1( }) }); - #[cfg(feature = "napi3")] - { - unsafe { - sys::napi_add_env_cleanup_hook(env, Some(remove_registered_classes), env as *mut c_void) - }; - } REGISTERED.store(true, Ordering::SeqCst); exports } -unsafe extern "C" fn remove_registered_classes(env: *mut c_void) { - let env = env as sys::napi_env; - if let Some(s) = REGISTERED_CLASSES.get() { - let registered_classes = unsafe { Box::from_raw(s.load(Ordering::Relaxed)) }; - registered_classes.iter().for_each(|(_, v)| { - unsafe { sys::napi_delete_reference(env, *v) }; - }); - s.store(ptr::null_mut(), Ordering::Relaxed); - } -} - pub(crate) unsafe extern "C" fn noop( env: sys::napi_env, _info: sys::napi_callback_info, diff --git a/crates/napi/src/tokio_runtime.rs b/crates/napi/src/tokio_runtime.rs index b2df5be2..7c7ac709 100644 --- a/crates/napi/src/tokio_runtime.rs +++ b/crates/napi/src/tokio_runtime.rs @@ -2,43 +2,12 @@ use std::future::Future; use std::ptr; use once_cell::sync::Lazy; -use tokio::{ - runtime::Handle, - sync::mpsc::{self, error::TrySendError}, -}; +use tokio::runtime::Runtime; use crate::{check_status, sys, JsDeferred, JsUnknown, NapiValue, Result}; -pub(crate) static RT: Lazy<(Handle, mpsc::Sender<()>)> = Lazy::new(|| { - let runtime = tokio::runtime::Runtime::new(); - let (sender, mut receiver) = mpsc::channel::<()>(1); - runtime - .map(|rt| { - let h = rt.handle(); - let handle = h.clone(); - handle.spawn(async move { - if receiver.recv().await.is_some() { - rt.shutdown_background(); - } - }); - - (handle, sender) - }) - .expect("Create tokio runtime failed") -}); - -#[ctor::dtor] -fn shutdown_tokio() { - let sender = &RT.1; - if let Err(e) = sender.clone().try_send(()) { - match e { - TrySendError::Closed(_) => {} - TrySendError::Full(_) => { - panic!("Send shutdown signal to tokio runtime failed, queue is full"); - } - } - } -} +pub(crate) static RT: Lazy = + Lazy::new(|| tokio::runtime::Runtime::new().expect("Create tokio runtime failed")); /// Spawns a future onto the Tokio runtime. /// @@ -48,7 +17,7 @@ pub fn spawn(fut: F) -> tokio::task::JoinHandle where F: 'static + Send + Future, { - RT.0.spawn(fut) + RT.spawn(fut) } /// Runs a future to completion @@ -58,7 +27,7 @@ pub fn block_on(fut: F) -> F::Output where F: 'static + Send + Future, { - RT.0.block_on(fut) + RT.block_on(fut) } // This function's signature must be kept in sync with the one in lib.rs, otherwise napi @@ -66,8 +35,9 @@ where /// If the feature `tokio_rt` has been enabled this will enter the runtime context and /// then call the provided closure. Otherwise it will just call the provided closure. +#[inline] pub fn within_runtime_if_available T, T>(f: F) -> T { - let _rt_guard = RT.0.enter(); + let _rt_guard = RT.enter(); f() } diff --git a/examples/napi/__test__/unload.spec.js b/examples/napi/__test__/unload.spec.js new file mode 100644 index 00000000..21a32ca2 --- /dev/null +++ b/examples/napi/__test__/unload.spec.js @@ -0,0 +1,11 @@ +// use the commonjs syntax to prevent compiler from transpiling the module syntax + +const test = require('ava').default + +test('unload module', (t) => { + const { add } = require('../index.node') + t.is(add(1, 2), 3) + delete require.cache[require.resolve('../index.node')] + const { add: add2 } = require('../index.node') + t.is(add2(1, 2), 3) +})