chore(napi): reduce the complex about destroying tokio runtime
This commit is contained in:
parent
a9f9dbb232
commit
c01bcecb2b
3 changed files with 19 additions and 55 deletions
|
@ -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,
|
||||
|
|
|
@ -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<Runtime> =
|
||||
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<F>(fut: F) -> tokio::task::JoinHandle<F::Output>
|
|||
where
|
||||
F: 'static + Send + Future<Output = ()>,
|
||||
{
|
||||
RT.0.spawn(fut)
|
||||
RT.spawn(fut)
|
||||
}
|
||||
|
||||
/// Runs a future to completion
|
||||
|
@ -58,7 +27,7 @@ pub fn block_on<F>(fut: F) -> F::Output
|
|||
where
|
||||
F: 'static + Send + Future<Output = ()>,
|
||||
{
|
||||
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<F: FnOnce() -> T, T>(f: F) -> T {
|
||||
let _rt_guard = RT.0.enter();
|
||||
let _rt_guard = RT.enter();
|
||||
f()
|
||||
}
|
||||
|
||||
|
|
11
examples/napi/__test__/unload.spec.js
Normal file
11
examples/napi/__test__/unload.spec.js
Normal file
|
@ -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)
|
||||
})
|
Loading…
Reference in a new issue