• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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