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