v8/platform.rs
1use crate::Isolate;
2use crate::isolate::RealIsolate;
3use crate::support::int;
4
5use crate::support::Opaque;
6use crate::support::Shared;
7use crate::support::SharedPtrBase;
8use crate::support::SharedRef;
9use crate::support::UniquePtr;
10use crate::support::UniqueRef;
11use crate::support::long;
12
13unsafe extern "C" {
14 fn v8__Platform__NewDefaultPlatform(
15 thread_pool_size: int,
16 idle_task_support: bool,
17 ) -> *mut Platform;
18 fn v8__Platform__NewUnprotectedDefaultPlatform(
19 thread_pool_size: int,
20 idle_task_support: bool,
21 ) -> *mut Platform;
22 fn v8__Platform__NewSingleThreadedDefaultPlatform(
23 idle_task_support: bool,
24 ) -> *mut Platform;
25 fn v8__Platform__DELETE(this: *mut Platform);
26
27 fn v8__Platform__PumpMessageLoop(
28 platform: *mut Platform,
29 isolate: *mut RealIsolate,
30 wait_for_work: bool,
31 ) -> bool;
32
33 fn v8__Platform__RunIdleTasks(
34 platform: *mut Platform,
35 isolate: *mut RealIsolate,
36 idle_time_in_seconds: f64,
37 );
38
39 fn v8__Platform__NotifyIsolateShutdown(
40 platform: *mut Platform,
41 isolate: *mut RealIsolate,
42 );
43
44 fn std__shared_ptr__v8__Platform__CONVERT__std__unique_ptr(
45 unique_ptr: UniquePtr<Platform>,
46 ) -> SharedPtrBase<Platform>;
47 fn std__shared_ptr__v8__Platform__get(
48 ptr: *const SharedPtrBase<Platform>,
49 ) -> *mut Platform;
50 fn std__shared_ptr__v8__Platform__COPY(
51 ptr: *const SharedPtrBase<Platform>,
52 ) -> SharedPtrBase<Platform>;
53 fn std__shared_ptr__v8__Platform__reset(ptr: *mut SharedPtrBase<Platform>);
54 fn std__shared_ptr__v8__Platform__use_count(
55 ptr: *const SharedPtrBase<Platform>,
56 ) -> long;
57}
58
59#[repr(C)]
60#[derive(Debug)]
61pub struct Platform(Opaque);
62
63/// Returns a new instance of the default v8::Platform implementation.
64///
65/// |thread_pool_size| is the number of worker threads to allocate for
66/// background jobs. If a value of zero is passed, a suitable default
67/// based on the current number of processors online will be chosen.
68/// If |idle_task_support| is enabled then the platform will accept idle
69/// tasks (IdleTasksEnabled will return true) and will rely on the embedder
70/// calling v8::platform::RunIdleTasks to process the idle tasks.
71///
72/// The default platform for v8 may include restrictions and caveats on thread
73/// creation and initialization. This platform should only be used in cases
74/// where v8 can be reliably initialized on the application's main thread, or
75/// the parent thread to all threads in the system that will use v8.
76///
77/// One example of a restriction is the use of Memory Protection Keys (pkeys) on
78/// modern Linux systems using modern Intel/AMD processors. This particular
79/// technology requires that all threads using v8 are created as descendent
80/// threads of the thread that called `v8::Initialize`.
81#[inline(always)]
82pub fn new_default_platform(
83 thread_pool_size: u32,
84 idle_task_support: bool,
85) -> UniqueRef<Platform> {
86 Platform::new(thread_pool_size, idle_task_support)
87}
88
89/// Creates a platform that is identical to the default platform, but does not
90/// enforce thread-isolated allocations. This may reduce security in some cases,
91/// so this method should be used with caution in cases where the threading
92/// guarantees of `new_default_platform` cannot be upheld (generally for tests).
93#[inline(always)]
94pub fn new_unprotected_default_platform(
95 thread_pool_size: u32,
96 idle_task_support: bool,
97) -> UniqueRef<Platform> {
98 Platform::new_unprotected(thread_pool_size, idle_task_support)
99}
100
101/// The same as new_default_platform() but disables the worker thread pool.
102/// It must be used with the --single-threaded V8 flag.
103///
104/// If |idle_task_support| is enabled then the platform will accept idle
105/// tasks (IdleTasksEnabled will return true) and will rely on the embedder
106/// calling v8::platform::RunIdleTasks to process the idle tasks.
107#[inline(always)]
108pub fn new_single_threaded_default_platform(
109 idle_task_support: bool,
110) -> UniqueRef<Platform> {
111 Platform::new_single_threaded(idle_task_support)
112}
113
114impl Platform {
115 /// Returns a new instance of the default v8::Platform implementation.
116 ///
117 /// |thread_pool_size| is the number of worker threads to allocate for
118 /// background jobs. If a value of zero is passed, a suitable default
119 /// based on the current number of processors online will be chosen.
120 /// If |idle_task_support| is enabled then the platform will accept idle
121 /// tasks (IdleTasksEnabled will return true) and will rely on the embedder
122 /// calling v8::platform::RunIdleTasks to process the idle tasks.
123 ///
124 /// The default platform for v8 may include restrictions and caveats on thread
125 /// creation and initialization. This platform should only be used in cases
126 /// where v8 can be reliably initialized on the application's main thread, or
127 /// the parent thread to all threads in the system that will use v8.
128 ///
129 /// One example of a restriction is the use of Memory Protection Keys (pkeys)
130 /// on modern Linux systems using modern Intel/AMD processors. This particular
131 /// technology requires that all threads using v8 are created as descendent
132 /// threads of the thread that called `v8::Initialize`.
133 #[inline(always)]
134 pub fn new(
135 thread_pool_size: u32,
136 idle_task_support: bool,
137 ) -> UniqueRef<Self> {
138 unsafe {
139 UniqueRef::from_raw(v8__Platform__NewDefaultPlatform(
140 thread_pool_size.min(16) as i32,
141 idle_task_support,
142 ))
143 }
144 }
145
146 /// Creates a platform that is identical to the default platform, but does not
147 /// enforce thread-isolated allocations. This may reduce security in some
148 /// cases, so this method should be used with caution in cases where the
149 /// threading guarantees of `new_default_platform` cannot be upheld (generally
150 /// for tests).
151 #[inline(always)]
152 pub fn new_unprotected(
153 thread_pool_size: u32,
154 idle_task_support: bool,
155 ) -> UniqueRef<Self> {
156 unsafe {
157 UniqueRef::from_raw(v8__Platform__NewUnprotectedDefaultPlatform(
158 thread_pool_size.min(16) as i32,
159 idle_task_support,
160 ))
161 }
162 }
163
164 /// The same as new() but disables the worker thread pool.
165 /// It must be used with the --single-threaded V8 flag.
166 ///
167 /// If |idle_task_support| is enabled then the platform will accept idle
168 /// tasks (IdleTasksEnabled will return true) and will rely on the embedder
169 /// calling v8::platform::RunIdleTasks to process the idle tasks.
170 #[inline(always)]
171 pub fn new_single_threaded(idle_task_support: bool) -> UniqueRef<Self> {
172 unsafe {
173 UniqueRef::from_raw(v8__Platform__NewSingleThreadedDefaultPlatform(
174 idle_task_support,
175 ))
176 }
177 }
178}
179
180impl Platform {
181 /// Pumps the message loop for the given isolate.
182 ///
183 /// The caller has to make sure that this is called from the right thread.
184 /// Returns true if a task was executed, and false otherwise. If the call to
185 /// PumpMessageLoop is nested within another call to PumpMessageLoop, only
186 /// nestable tasks may run. Otherwise, any task may run. Unless requested through
187 /// the |wait_for_work| parameter, this call does not block if no task is pending.
188 #[inline(always)]
189 pub fn pump_message_loop(
190 platform: &SharedRef<Self>,
191 isolate: &Isolate,
192 wait_for_work: bool,
193 ) -> bool {
194 unsafe {
195 v8__Platform__PumpMessageLoop(
196 &**platform as *const Self as *mut _,
197 isolate.as_real_ptr(),
198 wait_for_work,
199 )
200 }
201 }
202
203 /// Runs pending idle tasks for at most |idle_time_in_seconds| seconds.
204 ///
205 /// The caller has to make sure that this is called from the right thread.
206 /// This call does not block if no task is pending.
207 #[inline(always)]
208 pub fn run_idle_tasks(
209 platform: &SharedRef<Self>,
210 isolate: &Isolate,
211 idle_time_in_seconds: f64,
212 ) {
213 unsafe {
214 v8__Platform__RunIdleTasks(
215 &**platform as *const Self as *mut _,
216 isolate.as_real_ptr(),
217 idle_time_in_seconds,
218 );
219 }
220 }
221
222 /// Notifies the given platform about the Isolate getting deleted soon. Has to
223 /// be called for all Isolates which are deleted - unless we're shutting down
224 /// the platform.
225 ///
226 /// The |platform| has to be created using |NewDefaultPlatform|.
227 #[inline(always)]
228 pub(crate) unsafe fn notify_isolate_shutdown(
229 platform: &SharedRef<Self>,
230 isolate: &Isolate,
231 ) {
232 unsafe {
233 v8__Platform__NotifyIsolateShutdown(
234 &**platform as *const Self as *mut _,
235 isolate.as_real_ptr(),
236 );
237 }
238 }
239}
240
241impl Shared for Platform {
242 fn from_unique_ptr(unique_ptr: UniquePtr<Self>) -> SharedPtrBase<Self> {
243 unsafe {
244 std__shared_ptr__v8__Platform__CONVERT__std__unique_ptr(unique_ptr)
245 }
246 }
247 fn get(ptr: &SharedPtrBase<Self>) -> *const Self {
248 unsafe { std__shared_ptr__v8__Platform__get(ptr) }
249 }
250 fn clone(ptr: &SharedPtrBase<Self>) -> SharedPtrBase<Self> {
251 unsafe { std__shared_ptr__v8__Platform__COPY(ptr) }
252 }
253 fn reset(ptr: &mut SharedPtrBase<Self>) {
254 unsafe { std__shared_ptr__v8__Platform__reset(ptr) }
255 }
256 fn use_count(ptr: &SharedPtrBase<Self>) -> long {
257 unsafe { std__shared_ptr__v8__Platform__use_count(ptr) }
258 }
259}
260
261impl Drop for Platform {
262 fn drop(&mut self) {
263 unsafe { v8__Platform__DELETE(self) };
264 }
265}