1 #ifndef SRC_NODE_PLATFORM_H_ 2 #define SRC_NODE_PLATFORM_H_ 3 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6 #include <queue> 7 #include <unordered_map> 8 #include <vector> 9 #include <functional> 10 11 #include "libplatform/libplatform.h" 12 #include "node.h" 13 #include "node_mutex.h" 14 #include "uv.h" 15 16 namespace node { 17 18 class NodePlatform; 19 class IsolateData; 20 class PerIsolatePlatformData; 21 22 template <class T> 23 class TaskQueue { 24 public: 25 TaskQueue(); 26 ~TaskQueue() = default; 27 28 void Push(std::unique_ptr<T> task); 29 std::unique_ptr<T> Pop(); 30 std::unique_ptr<T> BlockingPop(); 31 std::queue<std::unique_ptr<T>> PopAll(); 32 void NotifyOfCompletion(); 33 void BlockingDrain(); 34 void Stop(); 35 36 private: 37 Mutex lock_; 38 ConditionVariable tasks_available_; 39 ConditionVariable tasks_drained_; 40 int outstanding_tasks_; 41 bool stopped_; 42 std::queue<std::unique_ptr<T>> task_queue_; 43 }; 44 45 struct DelayedTask { 46 std::unique_ptr<v8::Task> task; 47 uv_timer_t timer; 48 double timeout; 49 std::shared_ptr<PerIsolatePlatformData> platform_data; 50 }; 51 52 // This acts as the foreground task runner for a given Isolate. 53 class PerIsolatePlatformData : 54 public IsolatePlatformDelegate, 55 public v8::TaskRunner, 56 public std::enable_shared_from_this<PerIsolatePlatformData> { 57 public: 58 PerIsolatePlatformData(v8::Isolate* isolate, uv_loop_t* loop); 59 ~PerIsolatePlatformData() override; 60 61 std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner() override; 62 void PostTask(std::unique_ptr<v8::Task> task) override; 63 void PostIdleTask(std::unique_ptr<v8::IdleTask> task) override; 64 void PostDelayedTask(std::unique_ptr<v8::Task> task, 65 double delay_in_seconds) override; IdleTasksEnabled()66 bool IdleTasksEnabled() override { return false; } 67 68 // Non-nestable tasks are treated like regular tasks. NonNestableTasksEnabled()69 bool NonNestableTasksEnabled() const override { return true; } NonNestableDelayedTasksEnabled()70 bool NonNestableDelayedTasksEnabled() const override { return true; } 71 void PostNonNestableTask(std::unique_ptr<v8::Task> task) override; 72 void PostNonNestableDelayedTask(std::unique_ptr<v8::Task> task, 73 double delay_in_seconds) override; 74 75 void AddShutdownCallback(void (*callback)(void*), void* data); 76 void Shutdown(); 77 78 // Returns true if work was dispatched or executed. New tasks that are 79 // posted during flushing of the queue are postponed until the next 80 // flushing. 81 bool FlushForegroundTasksInternal(); 82 event_loop()83 const uv_loop_t* event_loop() const { return loop_; } 84 85 private: 86 void DeleteFromScheduledTasks(DelayedTask* task); 87 void DecreaseHandleCount(); 88 89 static void FlushTasks(uv_async_t* handle); 90 void RunForegroundTask(std::unique_ptr<v8::Task> task); 91 static void RunForegroundTask(uv_timer_t* timer); 92 93 struct ShutdownCallback { 94 void (*cb)(void*); 95 void* data; 96 }; 97 typedef std::vector<ShutdownCallback> ShutdownCbList; 98 ShutdownCbList shutdown_callbacks_; 99 // shared_ptr to self to keep this object alive during shutdown. 100 std::shared_ptr<PerIsolatePlatformData> self_reference_; 101 uint32_t uv_handle_count_ = 1; // 1 = flush_tasks_ 102 103 v8::Isolate* const isolate_; 104 uv_loop_t* const loop_; 105 uv_async_t* flush_tasks_ = nullptr; 106 TaskQueue<v8::Task> foreground_tasks_; 107 TaskQueue<DelayedTask> foreground_delayed_tasks_; 108 109 // Use a custom deleter because libuv needs to close the handle first. 110 typedef std::unique_ptr<DelayedTask, void(*)(DelayedTask*)> 111 DelayedTaskPointer; 112 std::vector<DelayedTaskPointer> scheduled_delayed_tasks_; 113 }; 114 115 // This acts as the single worker thread task runner for all Isolates. 116 class WorkerThreadsTaskRunner { 117 public: 118 explicit WorkerThreadsTaskRunner(int thread_pool_size); 119 120 void PostTask(std::unique_ptr<v8::Task> task); 121 void PostDelayedTask(std::unique_ptr<v8::Task> task, 122 double delay_in_seconds); 123 124 void BlockingDrain(); 125 void Shutdown(); 126 127 int NumberOfWorkerThreads() const; 128 129 private: 130 TaskQueue<v8::Task> pending_worker_tasks_; 131 132 class DelayedTaskScheduler; 133 std::unique_ptr<DelayedTaskScheduler> delayed_task_scheduler_; 134 135 std::vector<std::unique_ptr<uv_thread_t>> threads_; 136 }; 137 138 class NodePlatform : public MultiIsolatePlatform { 139 public: 140 NodePlatform(int thread_pool_size, 141 v8::TracingController* tracing_controller, 142 v8::PageAllocator* page_allocator = nullptr); 143 ~NodePlatform() override; 144 145 void DrainTasks(v8::Isolate* isolate) override; 146 void Shutdown(); 147 148 // v8::Platform implementation. 149 int NumberOfWorkerThreads() override; 150 void CallOnWorkerThread(std::unique_ptr<v8::Task> task) override; 151 void CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task, 152 double delay_in_seconds) override; 153 bool IdleTasksEnabled(v8::Isolate* isolate) override; 154 double MonotonicallyIncreasingTime() override; 155 double CurrentClockTimeMillis() override; 156 v8::TracingController* GetTracingController() override; 157 bool FlushForegroundTasks(v8::Isolate* isolate) override; 158 std::unique_ptr<v8::JobHandle> PostJob( 159 v8::TaskPriority priority, 160 std::unique_ptr<v8::JobTask> job_task) override; 161 162 void RegisterIsolate(v8::Isolate* isolate, uv_loop_t* loop) override; 163 void RegisterIsolate(v8::Isolate* isolate, 164 IsolatePlatformDelegate* delegate) override; 165 166 void UnregisterIsolate(v8::Isolate* isolate) override; 167 void AddIsolateFinishedCallback(v8::Isolate* isolate, 168 void (*callback)(void*), void* data) override; 169 170 std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner( 171 v8::Isolate* isolate) override; 172 173 Platform::StackTracePrinter GetStackTracePrinter() override; 174 v8::PageAllocator* GetPageAllocator() override; 175 176 private: 177 IsolatePlatformDelegate* ForIsolate(v8::Isolate* isolate); 178 std::shared_ptr<PerIsolatePlatformData> ForNodeIsolate(v8::Isolate* isolate); 179 180 Mutex per_isolate_mutex_; 181 using DelegatePair = std::pair< 182 IsolatePlatformDelegate*, std::shared_ptr<PerIsolatePlatformData>>; 183 std::unordered_map<v8::Isolate*, DelegatePair> per_isolate_; 184 185 v8::TracingController* tracing_controller_; 186 v8::PageAllocator* page_allocator_; 187 std::shared_ptr<WorkerThreadsTaskRunner> worker_thread_task_runner_; 188 bool has_shut_down_ = false; 189 }; 190 191 } // namespace node 192 193 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 194 195 #endif // SRC_NODE_PLATFORM_H_ 196