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