3
3
#include " node_mutex.h"
4
4
#include " v8-inspector.h"
5
5
6
+ #include < functional>
6
7
#include < unicode/unistr.h>
7
8
8
9
namespace node {
@@ -13,56 +14,72 @@ using v8_inspector::StringView;
13
14
using v8_inspector::StringBuffer;
14
15
15
16
template <typename T>
16
- class DeleteRequest : public Request {
17
+ class DeletableWrapper : public Deletable {
17
18
public:
18
- explicit DeleteRequest (T* object) : object_(object) {}
19
- void Call () override {
20
- delete object_;
19
+ explicit DeletableWrapper (std::unique_ptr<T> object)
20
+ : object_(std::move(object)) {}
21
+ ~DeletableWrapper () override = default ;
22
+
23
+ static T* get (MainThreadInterface* thread, int id) {
24
+ return
25
+ static_cast <DeletableWrapper<T>*>(thread->GetObject (id))->object_ .get ();
21
26
}
22
27
23
28
private:
24
- T* object_;
29
+ std::unique_ptr<T> object_;
25
30
};
26
31
27
- template <typename Target, typename Arg>
28
- class SingleArgumentFunctionCall : public Request {
29
- public:
30
- using Fn = void (Target::*)(Arg);
32
+ template <typename T>
33
+ std::unique_ptr<Deletable> WrapInDeletable (std::unique_ptr<T> object) {
34
+ return std::unique_ptr<DeletableWrapper<T>>(
35
+ new DeletableWrapper<T>(std::move (object)));
36
+ }
31
37
32
- SingleArgumentFunctionCall (Target* target, Fn fn, Arg argument)
33
- : target_(target),
34
- fn_ (fn),
35
- arg_(std::move(argument)) {}
38
+ template <typename Factory>
39
+ class CreateObjectRequest : public Request {
40
+ public:
41
+ CreateObjectRequest (int object_id, Factory factory)
42
+ : object_id_(object_id), factory_(std::move(factory)) {}
36
43
37
- void Call () override {
38
- Apply (target_, fn_, std::move (arg_ ));
44
+ void Call (MainThreadInterface* thread) {
45
+ thread-> AddObject (object_id_, WrapInDeletable ( factory_ (thread) ));
39
46
}
40
47
41
48
private:
42
- template <typename Element>
43
- void Apply (Element* target, Fn fn, Arg arg) {
44
- (target->*fn)(std::move (arg));
49
+ int object_id_;
50
+ Factory factory_;
51
+ };
52
+
53
+ template <typename Factory>
54
+ std::unique_ptr<Request> NewCreateRequest (int object_id, Factory factory) {
55
+ return std::unique_ptr<Request>(
56
+ new CreateObjectRequest<Factory>(object_id, std::move (factory)));
57
+ }
58
+
59
+ class DeleteRequest : public Request {
60
+ public:
61
+ explicit DeleteRequest (int object_id) : object_id_(object_id) {}
62
+
63
+ void Call (MainThreadInterface* thread) override {
64
+ thread->RemoveObject (object_id_);
45
65
}
46
66
47
- Target* target_;
48
- Fn fn_;
49
- Arg arg_;
67
+ private:
68
+ int object_id_;
50
69
};
51
70
52
- class PostMessageRequest : public Request {
71
+ template <typename Target, typename Fn>
72
+ class CallRequest : public Request {
53
73
public:
54
- PostMessageRequest (InspectorSessionDelegate* delegate,
55
- StringView message)
56
- : delegate_(delegate),
57
- message_ (StringBuffer::create(message)) {}
74
+ CallRequest (int id, Fn fn) : id_(id), fn_(std::move(fn)) {}
58
75
59
- void Call () override {
60
- delegate_-> SendMessageToFrontend (message_-> string ( ));
76
+ void Call (MainThreadInterface* thread ) override {
77
+ fn_ (DeletableWrapper<Target>:: get (thread, id_ ));
61
78
}
62
79
63
80
private:
64
- InspectorSessionDelegate* delegate_ ;
65
- std::unique_ptr<StringBuffer> message_ ;
81
+ int id_ ;
82
+ Fn fn_ ;
66
83
};
67
84
68
85
class DispatchMessagesTask : public v8 ::Task {
@@ -88,45 +105,63 @@ void DisposePairCallback(uv_handle_t* ref) {
88
105
template <typename T>
89
106
class AnotherThreadObjectReference {
90
107
public:
91
- // We create it on whatever thread, just make sure it gets disposed on the
92
- // proper thread.
93
- AnotherThreadObjectReference (std::shared_ptr<MainThreadHandle> thread,
94
- T* object)
95
- : thread_(thread), object_(object) {
108
+ AnotherThreadObjectReference (
109
+ std::shared_ptr<MainThreadHandle> thread, int object_id)
110
+ : thread_(thread), object_id_(object_id) {}
111
+
112
+ template <typename Factory>
113
+ AnotherThreadObjectReference (
114
+ std::shared_ptr<MainThreadHandle> thread, Factory factory)
115
+ : AnotherThreadObjectReference(thread, thread->newObjectId ()) {
116
+ thread_->Post (NewCreateRequest (object_id_, std::move (factory)));
96
117
}
97
118
AnotherThreadObjectReference (AnotherThreadObjectReference&) = delete;
98
119
99
120
~AnotherThreadObjectReference () {
100
121
// Disappearing thread may cause a memory leak
101
- CHECK (thread_->Post (
102
- std::unique_ptr<DeleteRequest<T>>(new DeleteRequest<T>(object_))));
103
- object_ = nullptr ;
122
+ thread_->Post (
123
+ std::unique_ptr<DeleteRequest>(new DeleteRequest (object_id_)));
104
124
}
105
125
106
- template <typename Fn, typename Arg>
107
- void Post (Fn fn, Arg argument) const {
108
- using R = SingleArgumentFunctionCall<T, Arg>;
109
- thread_->Post (std::unique_ptr<R>(new R (object_, fn, std::move (argument))));
126
+ template <typename Fn>
127
+ void Call (Fn fn) const {
128
+ using Request = CallRequest<T, Fn>;
129
+ thread_->Post (std::unique_ptr<Request>(
130
+ new Request (object_id_, std::move (fn))));
110
131
}
111
132
112
- T* get () const {
113
- return object_;
133
+ template <typename Arg>
134
+ void Call (void (T::*fn)(Arg), Arg argument) const {
135
+ Call (std::bind (Apply<Arg>, std::placeholders::_1, fn, std::move (argument)));
114
136
}
115
137
116
138
private:
139
+ // This has to use non-const reference to support std::bind with non-copyable
140
+ // types
141
+ template <typename Argument>
142
+ static void Apply (T* target, void (T::*fn)(Argument),
143
+ /* NOLINT (runtime/references) */ Argument& argument) {
144
+ (target->*fn)(std::move (argument));
145
+ }
146
+
117
147
std::shared_ptr<MainThreadHandle> thread_;
118
- T* object_ ;
148
+ const int object_id_ ;
119
149
};
120
150
121
151
class MainThreadSessionState {
122
152
public:
123
- MainThreadSessionState (
124
- std::shared_ptr<MainThreadHandle> thread,
125
- bool prevent_shutdown) : thread_(thread),
126
- prevent_shutdown_ (prevent_shutdown) {}
153
+ MainThreadSessionState (MainThreadInterface* thread, bool prevent_shutdown)
154
+ : thread_(thread),
155
+ prevent_shutdown_ (prevent_shutdown) {}
156
+
157
+ static std::unique_ptr<MainThreadSessionState> Create (
158
+ MainThreadInterface* thread, bool prevent_shutdown) {
159
+ return std::unique_ptr<MainThreadSessionState>(
160
+ new MainThreadSessionState (thread, prevent_shutdown));
161
+ }
127
162
128
163
void Connect (std::unique_ptr<InspectorSessionDelegate> delegate) {
129
- Agent* agent = thread_->GetInspectorAgent ();
164
+ Agent* agent = thread_->inspector_agent ();
130
165
if (agent != nullptr )
131
166
session_ = agent->Connect (std::move (delegate), prevent_shutdown_);
132
167
}
@@ -136,7 +171,7 @@ class MainThreadSessionState {
136
171
}
137
172
138
173
private:
139
- std::shared_ptr<MainThreadHandle> thread_;
174
+ MainThreadInterface* thread_;
140
175
bool prevent_shutdown_;
141
176
std::unique_ptr<InspectorSession> session_;
142
177
};
@@ -148,12 +183,14 @@ class CrossThreadInspectorSession : public InspectorSession {
148
183
std::shared_ptr<MainThreadHandle> thread,
149
184
std::unique_ptr<InspectorSessionDelegate> delegate,
150
185
bool prevent_shutdown)
151
- : state_(thread, new MainThreadSessionState(thread, prevent_shutdown)) {
152
- state_.Post (&MainThreadSessionState::Connect, std::move (delegate));
186
+ : state_(thread, std::bind(MainThreadSessionState::Create,
187
+ std::placeholders::_1,
188
+ prevent_shutdown)) {
189
+ state_.Call (&MainThreadSessionState::Connect, std::move (delegate));
153
190
}
154
191
155
192
void Dispatch (const StringView& message) override {
156
- state_.Post (&MainThreadSessionState::Dispatch,
193
+ state_.Call (&MainThreadSessionState::Dispatch,
157
194
StringBuffer::create (message));
158
195
}
159
196
@@ -163,13 +200,15 @@ class CrossThreadInspectorSession : public InspectorSession {
163
200
164
201
class ThreadSafeDelegate : public InspectorSessionDelegate {
165
202
public:
166
- ThreadSafeDelegate (std::shared_ptr<MainThreadHandle> thread,
167
- std::unique_ptr<InspectorSessionDelegate> delegate)
168
- : thread_(thread), delegate_(thread, delegate.release()) {}
203
+ ThreadSafeDelegate (std::shared_ptr<MainThreadHandle> thread, int object_id)
204
+ : thread_(thread), delegate_(thread, object_id) {}
169
205
170
206
void SendMessageToFrontend (const v8_inspector::StringView& message) override {
171
- thread_->Post (std::unique_ptr<Request>(
172
- new PostMessageRequest (delegate_.get (), message)));
207
+ delegate_.Call (
208
+ [m = StringBuffer::create (message)]
209
+ (InspectorSessionDelegate* delegate) {
210
+ delegate->SendMessageToFrontend (m->string ());
211
+ });
173
212
}
174
213
175
214
private:
@@ -252,7 +291,7 @@ void MainThreadInterface::DispatchMessages() {
252
291
MessageQueue::value_type task;
253
292
std::swap (dispatching_message_queue_.front (), task);
254
293
dispatching_message_queue_.pop_front ();
255
- task->Call ();
294
+ task->Call (this );
256
295
}
257
296
} while (had_messages);
258
297
dispatching_messages_ = false ;
@@ -264,6 +303,26 @@ std::shared_ptr<MainThreadHandle> MainThreadInterface::GetHandle() {
264
303
return handle_;
265
304
}
266
305
306
+ void MainThreadInterface::AddObject (int id,
307
+ std::unique_ptr<Deletable> object) {
308
+ CHECK_NE (nullptr , object);
309
+ managed_objects_[id] = std::move (object);
310
+ }
311
+
312
+ void MainThreadInterface::RemoveObject (int id) {
313
+ CHECK_EQ (1 , managed_objects_.erase (id));
314
+ }
315
+
316
+ Deletable* MainThreadInterface::GetObject (int id) {
317
+ auto iterator = managed_objects_.find (id);
318
+ // This would mean the object is requested after it was disposed, which is
319
+ // a coding error.
320
+ CHECK_NE (managed_objects_.end (), iterator);
321
+ Deletable* pointer = iterator->second .get ();
322
+ CHECK_NE (nullptr , pointer);
323
+ return pointer;
324
+ }
325
+
267
326
std::unique_ptr<StringBuffer> Utf8ToStringView (const std::string& message) {
268
327
icu::UnicodeString utf16 = icu::UnicodeString::fromUTF8 (
269
328
icu::StringPiece (message.data (), message.length ()));
@@ -303,10 +362,12 @@ Agent* MainThreadHandle::GetInspectorAgent() {
303
362
}
304
363
305
364
std::unique_ptr<InspectorSessionDelegate>
306
- MainThreadHandle::MakeThreadSafeDelegate (
365
+ MainThreadHandle::MakeDelegateThreadSafe (
307
366
std::unique_ptr<InspectorSessionDelegate> delegate) {
367
+ int id = newObjectId ();
368
+ main_thread_->AddObject (id, WrapInDeletable (std::move (delegate)));
308
369
return std::unique_ptr<InspectorSessionDelegate>(
309
- new ThreadSafeDelegate (shared_from_this (), std::move (delegate) ));
370
+ new ThreadSafeDelegate (shared_from_this (), id ));
310
371
}
311
372
312
373
bool MainThreadHandle::Expired () {
0 commit comments