/src/node/deps/v8/include/cppgc/platform.h
Line  | Count  | Source  | 
1  |  | // Copyright 2020 the V8 project authors. All rights reserved.  | 
2  |  | // Use of this source code is governed by a BSD-style license that can be  | 
3  |  | // found in the LICENSE file.  | 
4  |  |  | 
5  |  | #ifndef INCLUDE_CPPGC_PLATFORM_H_  | 
6  |  | #define INCLUDE_CPPGC_PLATFORM_H_  | 
7  |  |  | 
8  |  | #include <memory>  | 
9  |  |  | 
10  |  | #include "cppgc/source-location.h"  | 
11  |  | #include "v8-platform.h"  // NOLINT(build/include_directory)  | 
12  |  | #include "v8config.h"     // NOLINT(build/include_directory)  | 
13  |  |  | 
14  |  | namespace cppgc { | 
15  |  |  | 
16  |  | // TODO(v8:10346): Create separate includes for concepts that are not  | 
17  |  | // V8-specific.  | 
18  |  | using IdleTask = v8::IdleTask;  | 
19  |  | using JobHandle = v8::JobHandle;  | 
20  |  | using JobDelegate = v8::JobDelegate;  | 
21  |  | using JobTask = v8::JobTask;  | 
22  |  | using PageAllocator = v8::PageAllocator;  | 
23  |  | using Task = v8::Task;  | 
24  |  | using TaskPriority = v8::TaskPriority;  | 
25  |  | using TaskRunner = v8::TaskRunner;  | 
26  |  | using TracingController = v8::TracingController;  | 
27  |  |  | 
28  |  | /**  | 
29  |  |  * Platform interface used by Heap. Contains allocators and executors.  | 
30  |  |  */  | 
31  |  | class V8_EXPORT Platform { | 
32  |  |  public:  | 
33  |  |   virtual ~Platform() = default;  | 
34  |  |  | 
35  |  |   /**  | 
36  |  |    * \returns the allocator used by cppgc to allocate its heap and various  | 
37  |  |    * support structures. Returning nullptr results in using the `PageAllocator`  | 
38  |  |    * provided by `cppgc::InitializeProcess()` instead.  | 
39  |  |    */  | 
40  |  |   virtual PageAllocator* GetPageAllocator() = 0;  | 
41  |  |  | 
42  |  |   /**  | 
43  |  |    * Monotonically increasing time in seconds from an arbitrary fixed point in  | 
44  |  |    * the past. This function is expected to return at least  | 
45  |  |    * millisecond-precision values. For this reason,  | 
46  |  |    * it is recommended that the fixed point be no further in the past than  | 
47  |  |    * the epoch.  | 
48  |  |    **/  | 
49  |  |   virtual double MonotonicallyIncreasingTime() = 0;  | 
50  |  |  | 
51  |  |   /**  | 
52  |  |    * Foreground task runner that should be used by a Heap.  | 
53  |  |    */  | 
54  | 0  |   virtual std::shared_ptr<TaskRunner> GetForegroundTaskRunner() { | 
55  | 0  |     return GetForegroundTaskRunner(TaskPriority::kUserBlocking);  | 
56  | 0  |   }  | 
57  |  |  | 
58  |  |   /**  | 
59  |  |    * Returns a TaskRunner with a specific |priority| which can be used to post a  | 
60  |  |    * task on the foreground thread.  | 
61  |  |    */  | 
62  |  |   virtual std::shared_ptr<TaskRunner> GetForegroundTaskRunner(  | 
63  | 0  |       TaskPriority priority) { | 
64  | 0  |     return nullptr;  | 
65  | 0  |   }  | 
66  |  |  | 
67  |  |   /**  | 
68  |  |    * Posts `job_task` to run in parallel. Returns a `JobHandle` associated with  | 
69  |  |    * the `Job`, which can be joined or canceled.  | 
70  |  |    * This avoids degenerate cases:  | 
71  |  |    * - Calling `CallOnWorkerThread()` for each work item, causing significant  | 
72  |  |    *   overhead.  | 
73  |  |    * - Fixed number of `CallOnWorkerThread()` calls that split the work and  | 
74  |  |    *   might run for a long time. This is problematic when many components post  | 
75  |  |    *   "num cores" tasks and all expect to use all the cores. In these cases,  | 
76  |  |    *   the scheduler lacks context to be fair to multiple same-priority requests  | 
77  |  |    *   and/or ability to request lower priority work to yield when high priority  | 
78  |  |    *   work comes in.  | 
79  |  |    * A canonical implementation of `job_task` looks like:  | 
80  |  |    * \code  | 
81  |  |    * class MyJobTask : public JobTask { | 
82  |  |    *  public:  | 
83  |  |    *   MyJobTask(...) : worker_queue_(...) {} | 
84  |  |    *   // JobTask implementation.  | 
85  |  |    *   void Run(JobDelegate* delegate) override { | 
86  |  |    *     while (!delegate->ShouldYield()) { | 
87  |  |    *       // Smallest unit of work.  | 
88  |  |    *       auto work_item = worker_queue_.TakeWorkItem(); // Thread safe.  | 
89  |  |    *       if (!work_item) return;  | 
90  |  |    *       ProcessWork(work_item);  | 
91  |  |    *     }  | 
92  |  |    *   }  | 
93  |  |    *  | 
94  |  |    *   size_t GetMaxConcurrency() const override { | 
95  |  |    *     return worker_queue_.GetSize(); // Thread safe.  | 
96  |  |    *   }  | 
97  |  |    * };  | 
98  |  |    *  | 
99  |  |    * // ...  | 
100  |  |    * auto handle = PostJob(TaskPriority::kUserVisible,  | 
101  |  |    *                       std::make_unique<MyJobTask>(...));  | 
102  |  |    * handle->Join();  | 
103  |  |    * \endcode  | 
104  |  |    *  | 
105  |  |    * `PostJob()` and methods of the returned JobHandle/JobDelegate, must never  | 
106  |  |    * be called while holding a lock that could be acquired by `JobTask::Run()`  | 
107  |  |    * or `JobTask::GetMaxConcurrency()` -- that could result in a deadlock. This  | 
108  |  |    * is because (1) `JobTask::GetMaxConcurrency()` may be invoked while holding  | 
109  |  |    * internal lock (A), hence `JobTask::GetMaxConcurrency()` can only use a lock  | 
110  |  |    * (B) if that lock is *never* held while calling back into `JobHandle` from  | 
111  |  |    * any thread (A=>B/B=>A deadlock) and (2) `JobTask::Run()` or  | 
112  |  |    * `JobTask::GetMaxConcurrency()` may be invoked synchronously from  | 
113  |  |    * `JobHandle` (B=>JobHandle::foo=>B deadlock).  | 
114  |  |    *  | 
115  |  |    * A sufficient `PostJob()` implementation that uses the default Job provided  | 
116  |  |    * in libplatform looks like:  | 
117  |  |    * \code  | 
118  |  |    * std::unique_ptr<JobHandle> PostJob(  | 
119  |  |    *     TaskPriority priority, std::unique_ptr<JobTask> job_task) override { | 
120  |  |    *   return std::make_unique<DefaultJobHandle>(  | 
121  |  |    *       std::make_shared<DefaultJobState>(  | 
122  |  |    *           this, std::move(job_task), kNumThreads));  | 
123  |  |    * }  | 
124  |  |    * \endcode  | 
125  |  |    */  | 
126  |  |   virtual std::unique_ptr<JobHandle> PostJob(  | 
127  | 0  |       TaskPriority priority, std::unique_ptr<JobTask> job_task) { | 
128  | 0  |     return nullptr;  | 
129  | 0  |   }  | 
130  |  |  | 
131  |  |   /**  | 
132  |  |    * Returns an instance of a `TracingController`. This must be non-nullptr. The  | 
133  |  |    * default implementation returns an empty `TracingController` that consumes  | 
134  |  |    * trace data without effect.  | 
135  |  |    */  | 
136  |  |   virtual TracingController* GetTracingController();  | 
137  |  | };  | 
138  |  |  | 
139  |  | V8_EXPORT bool IsInitialized();  | 
140  |  |  | 
141  |  | /**  | 
142  |  |  * Process-global initialization of the garbage collector. Must be called before  | 
143  |  |  * creating a Heap.  | 
144  |  |  *  | 
145  |  |  * Can be called multiple times when paired with `ShutdownProcess()`.  | 
146  |  |  *  | 
147  |  |  * \param page_allocator The allocator used for maintaining meta data. Must stay  | 
148  |  |  *   always alive and not change between multiple calls to InitializeProcess. If  | 
149  |  |  *   no allocator is provided, a default internal version will be used.  | 
150  |  |  * \param desired_heap_size Desired amount of virtual address space to reserve  | 
151  |  |  *   for the heap, in bytes. Actual size will be clamped to minimum and maximum  | 
152  |  |  *   values based on compile-time settings and may be rounded up. If this  | 
153  |  |  *   parameter is zero, a default value will be used.  | 
154  |  |  */  | 
155  |  | V8_EXPORT void InitializeProcess(PageAllocator* page_allocator = nullptr,  | 
156  |  |                                  size_t desired_heap_size = 0);  | 
157  |  |  | 
158  |  | /**  | 
159  |  |  * Must be called after destroying the last used heap. Some process-global  | 
160  |  |  * metadata may not be returned and reused upon a subsequent  | 
161  |  |  * `InitializeProcess()` call.  | 
162  |  |  */  | 
163  |  | V8_EXPORT void ShutdownProcess();  | 
164  |  |  | 
165  |  | namespace internal { | 
166  |  |  | 
167  |  | V8_EXPORT void Fatal(const std::string& reason = std::string(),  | 
168  |  |                      SourceLocation = SourceLocation::Current());  | 
169  |  |  | 
170  |  | }  // namespace internal  | 
171  |  |  | 
172  |  | }  // namespace cppgc  | 
173  |  |  | 
174  |  | #endif  // INCLUDE_CPPGC_PLATFORM_H_  |