summaryrefslogtreecommitdiff
path: root/cli/napi/async.rs
diff options
context:
space:
mode:
authorMatt Mastracci <matthew@mastracci.com>2023-12-11 10:52:55 -0700
committerGitHub <noreply@github.com>2023-12-11 10:52:55 -0700
commitd13e45f2b3e50b85953c31d9c16e35d0cd87545f (patch)
tree1b206fa8dafc4ee23cebfd586a58a192b3557d66 /cli/napi/async.rs
parenta272bc1bd0793b2f522e4e611963231dc344531f (diff)
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 <matthew@mastracci.com> Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
Diffstat (limited to 'cli/napi/async.rs')
-rw-r--r--cli/napi/async.rs25
1 files changed, 19 insertions, 6 deletions
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<T>(*const T);
+ unsafe impl<T> Send for SendPtr<T> {}
+ unsafe impl<T> Sync for SendPtr<T> {}
+ let send_env = SendPtr(env_ptr);
+
+ #[inline(always)]
+ fn do_work(ptr: SendPtr<Env>, 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
}