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 ~NodePlatform() override; 143 144 void DrainTasks(v8::Isolate* isolate) override; 145 void Shutdown(); 146 147 // v8::Platform implementation. 148 int NumberOfWorkerThreads() override; 149 void CallOnWorkerThread(std::unique_ptr<v8::Task> task) override; 150 void CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task, 151 double delay_in_seconds) override; 152 bool IdleTasksEnabled(v8::Isolate* isolate) override; 153 double MonotonicallyIncreasingTime() override; 154 double CurrentClockTimeMillis() override; 155 v8::TracingController* GetTracingController() override; 156 bool FlushForegroundTasks(v8::Isolate* isolate) override; 157 158 void RegisterIsolate(v8::Isolate* isolate, uv_loop_t* loop) override; 159 void RegisterIsolate(v8::Isolate* isolate, 160 IsolatePlatformDelegate* delegate) override; 161 162 void UnregisterIsolate(v8::Isolate* isolate) override; 163 void AddIsolateFinishedCallback(v8::Isolate* isolate, 164 void (*callback)(void*), void* data) override; 165 166 std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner( 167 v8::Isolate* isolate) override; 168 169 Platform::StackTracePrinter GetStackTracePrinter() override; 170 171 private: 172 IsolatePlatformDelegate* ForIsolate(v8::Isolate* isolate); 173 std::shared_ptr<PerIsolatePlatformData> ForNodeIsolate(v8::Isolate* isolate); 174 175 Mutex per_isolate_mutex_; 176 using DelegatePair = std::pair< 177 IsolatePlatformDelegate*, std::shared_ptr<PerIsolatePlatformData>>; 178 std::unordered_map<v8::Isolate*, DelegatePair> per_isolate_; 179 180 v8::TracingController* tracing_controller_; 181 std::shared_ptr<WorkerThreadsTaskRunner> worker_thread_task_runner_; 182 bool has_shut_down_ = false; 183 }; 184 185 } // namespace node 186 187 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 188 189 #endif // SRC_NODE_PLATFORM_H_ 190