GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_messaging.h Lines: 4 10 40.0 %
Date: 2020-02-19 22:14:06 Branches: 0 0 - %

Line Branch Exec Source
1
#ifndef SRC_NODE_MESSAGING_H_
2
#define SRC_NODE_MESSAGING_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "env.h"
7
#include "node_mutex.h"
8
#include <list>
9
10
namespace node {
11
namespace worker {
12
13
class MessagePortData;
14
class MessagePort;
15
16
typedef MaybeStackBuffer<v8::Local<v8::Value>, 8> TransferList;
17
18
// Represents a single communication message.
19
339791
class Message : public MemoryRetainer {
20
 public:
21
  // Create a Message with a specific underlying payload, in the format of the
22
  // V8 ValueSerializer API. If `payload` is empty, this message indicates
23
  // that the receiving message port should close itself.
24
  explicit Message(MallocedBuffer<char>&& payload = MallocedBuffer<char>());
25
26
106006
  Message(Message&& other) = default;
27
  Message& operator=(Message&& other) = default;
28
  Message& operator=(const Message&) = delete;
29
  Message(const Message&) = delete;
30
31
  // Whether this is a message indicating that the port is to be closed.
32
  // This is the last message to be received by a MessagePort.
33
  bool IsCloseMessage() const;
34
35
  // Deserialize the contained JS value. May only be called once, and only
36
  // after Serialize() has been called (e.g. by another thread).
37
  v8::MaybeLocal<v8::Value> Deserialize(Environment* env,
38
                                        v8::Local<v8::Context> context);
39
40
  // Serialize a JS value, and optionally transfer objects, into this message.
41
  // The Message object retains ownership of all transferred objects until
42
  // deserialization.
43
  // The source_port parameter, if provided, will make Serialize() throw a
44
  // "DataCloneError" DOMException if source_port is found in transfer_list.
45
  v8::Maybe<bool> Serialize(Environment* env,
46
                            v8::Local<v8::Context> context,
47
                            v8::Local<v8::Value> input,
48
                            const TransferList& transfer_list,
49
                            v8::Local<v8::Object> source_port =
50
                                v8::Local<v8::Object>());
51
52
  // Internal method of Message that is called when a new SharedArrayBuffer
53
  // object is encountered in the incoming value's structure.
54
  void AddSharedArrayBuffer(std::shared_ptr<v8::BackingStore> backing_store);
55
  // Internal method of Message that is called once serialization finishes
56
  // and that transfers ownership of `data` to this message.
57
  void AddMessagePort(std::unique_ptr<MessagePortData>&& data);
58
  // Internal method of Message that is called when a new WebAssembly.Module
59
  // object is encountered in the incoming value's structure.
60
  uint32_t AddWASMModule(v8::CompiledWasmModule&& mod);
61
62
  // The MessagePorts that will be transferred, as recorded by Serialize().
63
  // Used for warning user about posting the target MessagePort to itself,
64
  // which will as a side effect destroy the communication channel.
65
43109
  const std::vector<std::unique_ptr<MessagePortData>>& message_ports() const {
66
43109
    return message_ports_;
67
  }
68
69
  void MemoryInfo(MemoryTracker* tracker) const override;
70
71
  SET_MEMORY_INFO_NAME(Message)
72
  SET_SELF_SIZE(Message)
73
74
 private:
75
  MallocedBuffer<char> main_message_buf_;
76
  std::vector<std::shared_ptr<v8::BackingStore>> array_buffers_;
77
  std::vector<std::shared_ptr<v8::BackingStore>> shared_array_buffers_;
78
  std::vector<std::unique_ptr<MessagePortData>> message_ports_;
79
  std::vector<v8::CompiledWasmModule> wasm_modules_;
80
81
  friend class MessagePort;
82
};
83
84
// This contains all data for a `MessagePort` instance that is not tied to
85
// a specific Environment/Isolate/event loop, for easier transfer between those.
86
class MessagePortData : public MemoryRetainer {
87
 public:
88
  explicit MessagePortData(MessagePort* owner);
89
  ~MessagePortData() override;
90
91
  MessagePortData(MessagePortData&& other) = delete;
92
  MessagePortData& operator=(MessagePortData&& other) = delete;
93
  MessagePortData(const MessagePortData& other) = delete;
94
  MessagePortData& operator=(const MessagePortData& other) = delete;
95
96
  // Add a message to the incoming queue and notify the receiver.
97
  // This may be called from any thread.
98
  void AddToIncomingQueue(Message&& message);
99
100
  // Turns `a` and `b` into siblings, i.e. connects the sending side of one
101
  // to the receiving side of the other. This is not thread-safe.
102
  static void Entangle(MessagePortData* a, MessagePortData* b);
103
104
  // Removes any possible sibling. This is thread-safe (it acquires both
105
  // `sibling_mutex_` and `mutex_`), and has to be because it is called once
106
  // the corresponding JS handle handle wants to close
107
  // which can happen on either side of a worker.
108
  void Disentangle();
109
110
  void MemoryInfo(MemoryTracker* tracker) const override;
111
112
  SET_MEMORY_INFO_NAME(MessagePortData)
113
  SET_SELF_SIZE(MessagePortData)
114
115
 private:
116
  // This mutex protects all fields below it, with the exception of
117
  // sibling_.
118
  mutable Mutex mutex_;
119
  std::list<Message> incoming_messages_;
120
  MessagePort* owner_ = nullptr;
121
  // This mutex protects the sibling_ field and is shared between two entangled
122
  // MessagePorts. If both mutexes are acquired, this one needs to be
123
  // acquired first.
124
  std::shared_ptr<Mutex> sibling_mutex_ = std::make_shared<Mutex>();
125
  MessagePortData* sibling_ = nullptr;
126
127
  friend class MessagePort;
128
};
129
130
// A message port that receives messages from other threads, including
131
// the uv_async_t handle that is used to notify the current event loop of
132
// new incoming messages.
133
class MessagePort : public HandleWrap {
134
 private:
135
  // Create a new MessagePort. The `context` argument specifies the Context
136
  // instance that is used for creating the values emitted from this port.
137
  // This is called by MessagePort::New(), which is the public API used for
138
  // creating MessagePort instances.
139
  MessagePort(Environment* env,
140
              v8::Local<v8::Context> context,
141
              v8::Local<v8::Object> wrap);
142
143
 public:
144
  ~MessagePort() override;
145
146
  // Create a new message port instance, optionally over an existing
147
  // `MessagePortData` object.
148
  static MessagePort* New(Environment* env,
149
                          v8::Local<v8::Context> context,
150
                          std::unique_ptr<MessagePortData> data = nullptr);
151
152
  // Send a message, i.e. deliver it into the sibling's incoming queue.
153
  // If this port is closed, or if there is no sibling, this message is
154
  // serialized with transfers, then silently discarded.
155
  v8::Maybe<bool> PostMessage(Environment* env,
156
                              v8::Local<v8::Value> message,
157
                              const TransferList& transfer);
158
159
  // Start processing messages on this port as a receiving end.
160
  void Start();
161
  // Stop processing messages on this port as a receiving end.
162
  void Stop();
163
164
  /* constructor */
165
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
166
  /* prototype methods */
167
  static void PostMessage(const v8::FunctionCallbackInfo<v8::Value>& args);
168
  static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
169
  static void Stop(const v8::FunctionCallbackInfo<v8::Value>& args);
170
  static void Drain(const v8::FunctionCallbackInfo<v8::Value>& args);
171
  static void ReceiveMessage(const v8::FunctionCallbackInfo<v8::Value>& args);
172
173
  /* static */
174
  static void MoveToContext(const v8::FunctionCallbackInfo<v8::Value>& args);
175
176
  // Turns `a` and `b` into siblings, i.e. connects the sending side of one
177
  // to the receiving side of the other. This is not thread-safe.
178
  static void Entangle(MessagePort* a, MessagePort* b);
179
  static void Entangle(MessagePort* a, MessagePortData* b);
180
181
  // Detach this port's data for transferring. After this, the MessagePortData
182
  // is no longer associated with this handle, although it can still receive
183
  // messages.
184
  std::unique_ptr<MessagePortData> Detach();
185
186
  void Close(
187
      v8::Local<v8::Value> close_callback = v8::Local<v8::Value>()) override;
188
189
  // Returns true if either data_ has been freed, or if the handle is being
190
  // closed. Equivalent to the [[Detached]] internal slot in the HTML Standard.
191
  //
192
  // If checking if a JavaScript MessagePort object is detached, this method
193
  // alone is often not enough, since the backing C++ MessagePort object may
194
  // have been deleted already. For all intents and purposes, an object with a
195
  // NULL pointer to the C++ MessagePort object is also detached.
196
  inline bool IsDetached() const;
197
198
  void MemoryInfo(MemoryTracker* tracker) const override;
199
  SET_MEMORY_INFO_NAME(MessagePort)
200
  SET_SELF_SIZE(MessagePort)
201
202
 private:
203
  void OnClose() override;
204
  void OnMessage();
205
  void TriggerAsync();
206
  v8::MaybeLocal<v8::Value> ReceiveMessage(v8::Local<v8::Context> context,
207
                                           bool only_if_receiving);
208
209
  std::unique_ptr<MessagePortData> data_ = nullptr;
210
  bool receiving_messages_ = false;
211
  uv_async_t async_;
212
  v8::Global<v8::Function> emit_message_fn_;
213
214
  friend class MessagePortData;
215
};
216
217
v8::Local<v8::FunctionTemplate> GetMessagePortConstructorTemplate(
218
    Environment* env);
219
220
}  // namespace worker
221
}  // namespace node
222
223
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
224
225
226
#endif  // SRC_NODE_MESSAGING_H_