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 "tracing/agent.h" 15 #include "uv.h" 16 17 namespace node { 18 19 class NodePlatform; 20 class IsolateData; 21 class PerIsolatePlatformData; 22 23 template <class T> 24 class TaskQueue { 25 public: 26 TaskQueue(); ~TaskQueue()27 ~TaskQueue() {} 28 29 void Push(std::unique_ptr<T> task); 30 std::unique_ptr<T> Pop(); 31 std::unique_ptr<T> BlockingPop(); 32 std::queue<std::unique_ptr<T>> PopAll(); 33 void NotifyOfCompletion(); 34 void BlockingDrain(); 35 void Stop(); 36 37 private: 38 Mutex lock_; 39 ConditionVariable tasks_available_; 40 ConditionVariable tasks_drained_; 41 int outstanding_tasks_; 42 bool stopped_; 43 std::queue<std::unique_ptr<T>> task_queue_; 44 }; 45 46 struct DelayedTask { 47 std::unique_ptr<v8::Task> task; 48 uv_timer_t timer; 49 double timeout; 50 std::shared_ptr<PerIsolatePlatformData> platform_data; 51 }; 52 53 // This acts as the foreground task runner for a given Isolate. 54 class PerIsolatePlatformData : 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(); 60 61 void PostTask(std::unique_ptr<v8::Task> task) override; 62 void PostIdleTask(std::unique_ptr<v8::IdleTask> task) override; 63 void PostDelayedTask(std::unique_ptr<v8::Task> task, 64 double delay_in_seconds) override; IdleTasksEnabled()65 bool IdleTasksEnabled() override { return false; } 66 67 void Shutdown(); 68 69 void ref(); 70 int unref(); 71 72 // Returns true if work was dispatched or executed. New tasks that are 73 // posted during flushing of the queue are postponed until the next 74 // flushing. 75 bool FlushForegroundTasksInternal(); 76 void CancelPendingDelayedTasks(); 77 event_loop()78 const uv_loop_t* event_loop() const { return loop_; } 79 80 private: 81 void DeleteFromScheduledTasks(DelayedTask* task); 82 83 static void FlushTasks(uv_async_t* handle); 84 static void RunForegroundTask(std::unique_ptr<v8::Task> task); 85 static void RunForegroundTask(uv_timer_t* timer); 86 87 int ref_count_ = 1; 88 uv_loop_t* const loop_; 89 uv_async_t* flush_tasks_ = nullptr; 90 TaskQueue<v8::Task> foreground_tasks_; 91 TaskQueue<DelayedTask> foreground_delayed_tasks_; 92 93 // Use a custom deleter because libuv needs to close the handle first. 94 typedef std::unique_ptr<DelayedTask, std::function<void(DelayedTask*)>> 95 DelayedTaskPointer; 96 std::vector<DelayedTaskPointer> scheduled_delayed_tasks_; 97 }; 98 99 // This acts as the single background task runner for all Isolates. 100 class BackgroundTaskRunner : public v8::TaskRunner { 101 public: 102 explicit BackgroundTaskRunner(int thread_pool_size); 103 104 void PostTask(std::unique_ptr<v8::Task> task) override; 105 void PostIdleTask(std::unique_ptr<v8::IdleTask> task) override; 106 void PostDelayedTask(std::unique_ptr<v8::Task> task, 107 double delay_in_seconds) override; IdleTasksEnabled()108 bool IdleTasksEnabled() override { return false; }; 109 110 void BlockingDrain(); 111 void Shutdown(); 112 113 size_t NumberOfAvailableBackgroundThreads() const; 114 115 private: 116 TaskQueue<v8::Task> background_tasks_; 117 118 class DelayedTaskScheduler; 119 std::unique_ptr<DelayedTaskScheduler> delayed_task_scheduler_; 120 121 std::vector<std::unique_ptr<uv_thread_t>> threads_; 122 }; 123 124 class NodePlatform : public MultiIsolatePlatform { 125 public: 126 NodePlatform(int thread_pool_size, 127 node::tracing::TracingController* tracing_controller); ~NodePlatform()128 virtual ~NodePlatform() {} 129 130 void DrainBackgroundTasks(v8::Isolate* isolate) override; 131 void CancelPendingDelayedTasks(v8::Isolate* isolate) override; 132 void Shutdown(); 133 134 // v8::Platform implementation. 135 size_t NumberOfAvailableBackgroundThreads() override; 136 void CallOnBackgroundThread(v8::Task* task, 137 ExpectedRuntime expected_runtime) override; 138 void CallOnForegroundThread(v8::Isolate* isolate, v8::Task* task) override; 139 void CallDelayedOnForegroundThread(v8::Isolate* isolate, v8::Task* task, 140 double delay_in_seconds) override; 141 bool IdleTasksEnabled(v8::Isolate* isolate) override; 142 double MonotonicallyIncreasingTime() override; 143 double CurrentClockTimeMillis() override; 144 node::tracing::TracingController* GetTracingController() override; 145 bool FlushForegroundTasks(v8::Isolate* isolate) override; 146 147 void RegisterIsolate(IsolateData* isolate_data, uv_loop_t* loop) override; 148 void UnregisterIsolate(IsolateData* isolate_data) override; 149 150 std::shared_ptr<v8::TaskRunner> GetBackgroundTaskRunner( 151 v8::Isolate* isolate) override; 152 std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner( 153 v8::Isolate* isolate) override; 154 155 private: 156 std::shared_ptr<PerIsolatePlatformData> ForIsolate(v8::Isolate* isolate); 157 158 Mutex per_isolate_mutex_; 159 std::unordered_map<v8::Isolate*, 160 std::shared_ptr<PerIsolatePlatformData>> per_isolate_; 161 162 node::tracing::TracingController* tracing_controller_; 163 std::shared_ptr<BackgroundTaskRunner> background_task_runner_; 164 }; 165 166 } // namespace node 167 168 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 169 170 #endif // SRC_NODE_PLATFORM_H_ 171