From d13e45f2b3e50b85953c31d9c16e35d0cd87545f Mon Sep 17 00:00:00 2001 From: Matt Mastracci Date: Mon, 11 Dec 2023 10:52:55 -0700 Subject: perf(ext/napi): port NAPI to v8 tasks (#21406) Part 2 of removing middleware. This is somewhat awkward because `V8CrossThreadTaskSpawner` requires tasks to be `Send`, but NAPI makes heavy use of `!Send` pointers. In addition, Rust causes a closure to be `!Send` if you pull a `!Send` value out of a struct. --------- Signed-off-by: Matt Mastracci Co-authored-by: Divy Srivastava --- cli/napi/async.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'cli/napi/async.rs') diff --git a/cli/napi/async.rs b/cli/napi/async.rs index 48de36728..1fb0c6374 100644 --- a/cli/napi/async.rs +++ b/cli/napi/async.rs @@ -11,6 +11,9 @@ pub struct AsyncWork { pub complete: napi_async_complete_callback, } +unsafe impl Send for AsyncWork {} +unsafe impl Sync for AsyncWork {} + #[napi_sym::napi_sym] fn napi_create_async_work( _env: *mut Env, @@ -61,12 +64,22 @@ fn napi_queue_async_work( return napi_invalid_arg; }; - let fut = Box::new(move || { - (work.execute)(env_ptr as napi_env, work.data); - // Note: Must be called from the loop thread. - (work.complete)(env_ptr as napi_env, napi_ok, work.data); - }); - env.add_async_work(fut); + #[repr(transparent)] + struct SendPtr(*const T); + unsafe impl Send for SendPtr {} + unsafe impl Sync for SendPtr {} + let send_env = SendPtr(env_ptr); + + #[inline(always)] + fn do_work(ptr: SendPtr, work: &AsyncWork) { + // SAFETY: This is a valid async work queue call and it runs on the event loop thread + unsafe { + (work.execute)(ptr.0 as napi_env, work.data); + (work.complete)(ptr.0 as napi_env, napi_ok, work.data); + } + } + + env.add_async_work(move || do_work(send_env, work)); napi_ok } -- cgit v1.2.3