GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_platform.h Lines: 2 4 50.0 %
Date: 2022-08-28 04:20:35 Branches: 0 0 - %

Line Branch Exec Source
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
24716
  ~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;
66
  bool IdleTasksEnabled() override { return false; }
67
68
  // Non-nestable tasks are treated like regular tasks.
69
17273
  bool NonNestableTasksEnabled() const override { return true; }
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
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_