-
Notifications
You must be signed in to change notification settings - Fork 375
feat: add PlatformImpl trait for custom platform callbacks #1924
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
a398d75
e1d44b3
299ff07
2ccc554
0dccadf
70228eb
c512ea4
4e45ca5
fe87f83
73dbcfc
0693f56
53e1c12
a56cc25
1b1694c
1062e03
aa5d6ee
03c0a0d
ae4022b
e34bb9d
da158c3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,11 @@ unsafe extern "C" { | |
| fn v8__Platform__NewSingleThreadedDefaultPlatform( | ||
| idle_task_support: bool, | ||
| ) -> *mut Platform; | ||
| fn v8__Platform__NewNotifyingPlatform( | ||
| thread_pool_size: int, | ||
| idle_task_support: bool, | ||
| context: *mut std::ffi::c_void, | ||
| ) -> *mut Platform; | ||
| fn v8__Platform__DELETE(this: *mut Platform); | ||
|
|
||
| fn v8__Platform__PumpMessageLoop( | ||
|
|
@@ -60,6 +65,51 @@ unsafe extern "C" { | |
| #[derive(Debug)] | ||
| pub struct Platform(Opaque); | ||
|
|
||
| /// Trait for receiving notifications when foreground tasks are posted to an | ||
| /// isolate's task runner. Implementations must be thread-safe as callbacks | ||
| /// can fire from any V8 background thread. | ||
| /// | ||
| /// This follows the trait-based pattern used by the inspector API | ||
| /// (`V8InspectorClientImpl`, `ChannelImpl`). | ||
| pub trait ForegroundTaskCallback: Send + Sync { | ||
|
||
| /// Called when a foreground task has been posted for the given isolate. | ||
| /// | ||
| /// `isolate_ptr` is the raw `v8::Isolate*` pointer of the target isolate. | ||
| /// `delay_in_seconds` is 0.0 for immediate tasks, or the delay before the | ||
| /// task should be executed. For delayed tasks, the embedder should schedule | ||
| /// a wake-up after the given delay (e.g. via a timer in tokio). | ||
| /// | ||
| /// This may be called from ANY thread (V8 background threads, etc.). | ||
| fn on_foreground_task_posted( | ||
| &self, | ||
| isolate_ptr: *mut std::ffi::c_void, | ||
| delay_in_seconds: f64, | ||
| ); | ||
| } | ||
|
|
||
| // FFI callbacks called from C++ NotifyingPlatform/NotifyingTaskRunner. | ||
| // `context` is a raw pointer to a `Box<dyn ForegroundTaskCallback>`. | ||
|
|
||
| #[unsafe(no_mangle)] | ||
| unsafe extern "C" fn v8__Platform__NotifyingPlatform__onForegroundTaskPosted( | ||
| context: *mut std::ffi::c_void, | ||
| isolate: *mut std::ffi::c_void, | ||
| delay_in_seconds: f64, | ||
| ) { | ||
| let callback = | ||
| unsafe { &*(context as *const Box<dyn ForegroundTaskCallback>) }; | ||
| callback.on_foreground_task_posted(isolate, delay_in_seconds); | ||
| } | ||
|
|
||
| #[unsafe(no_mangle)] | ||
| unsafe extern "C" fn v8__Platform__NotifyingPlatform__dropContext( | ||
| context: *mut std::ffi::c_void, | ||
| ) { | ||
| unsafe { | ||
| let _ = Box::from_raw(context as *mut Box<dyn ForegroundTaskCallback>); | ||
| } | ||
| } | ||
|
|
||
| /// Returns a new instance of the default v8::Platform implementation. | ||
| /// | ||
| /// |thread_pool_size| is the number of worker threads to allocate for | ||
|
|
@@ -111,6 +161,28 @@ pub fn new_single_threaded_default_platform( | |
| Platform::new_single_threaded(idle_task_support) | ||
| } | ||
|
|
||
| /// Creates a NotifyingPlatform that wraps DefaultPlatform and calls the | ||
| /// provided [`ForegroundTaskCallback`] whenever a foreground task is posted | ||
| /// for any isolate. | ||
| /// | ||
| /// This allows embedders to wake their event loop when V8 background threads | ||
| /// complete work and post foreground continuations (e.g. background compilation | ||
| /// finishing, Atomics.waitAsync resolving). For delayed tasks, the embedder | ||
| /// should schedule a wake-up after `delay_in_seconds` (e.g. via a timer). | ||
| /// | ||
| /// The callback may be invoked from ANY thread (V8 background threads, etc.) | ||
| /// and must be safe to call concurrently. | ||
| /// | ||
| /// Thread-isolated allocations are disabled (same as `new_unprotected_default_platform`). | ||
| #[inline(always)] | ||
| pub fn new_notifying_platform( | ||
| thread_pool_size: u32, | ||
| idle_task_support: bool, | ||
| callback: impl ForegroundTaskCallback + 'static, | ||
| ) -> UniqueRef<Platform> { | ||
| Platform::new_notifying(thread_pool_size, idle_task_support, callback) | ||
| } | ||
|
|
||
| impl Platform { | ||
| /// Returns a new instance of the default v8::Platform implementation. | ||
| /// | ||
|
|
@@ -175,6 +247,31 @@ impl Platform { | |
| )) | ||
| } | ||
| } | ||
|
|
||
| /// Creates a NotifyingPlatform (subclass of DefaultPlatform) that dispatches | ||
| /// to the provided [`ForegroundTaskCallback`] whenever a foreground task is | ||
| /// posted for an isolate. | ||
| /// | ||
| /// The callback trait object is owned by the platform and will be dropped | ||
| /// when the platform is destroyed. | ||
| #[inline(always)] | ||
| pub fn new_notifying( | ||
| thread_pool_size: u32, | ||
| idle_task_support: bool, | ||
| callback: impl ForegroundTaskCallback + 'static, | ||
| ) -> UniqueRef<Self> { | ||
| // Double-box: inner Box<dyn> is a fat pointer, outer Box gives us a | ||
| // thin pointer we can pass through C++ void*. | ||
| let boxed: Box<dyn ForegroundTaskCallback> = Box::new(callback); | ||
| let context = Box::into_raw(Box::new(boxed)) as *mut std::ffi::c_void; | ||
| unsafe { | ||
| UniqueRef::from_raw(v8__Platform__NewNotifyingPlatform( | ||
| thread_pool_size.min(16) as i32, | ||
| idle_task_support, | ||
| context, | ||
| )) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl Platform { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.