33#include " node_mutex.h"
44#include " v8-inspector.h"
55
6+ #include < functional>
67#include < unicode/unistr.h>
78
89namespace node {
@@ -13,56 +14,72 @@ using v8_inspector::StringView;
1314using v8_inspector::StringBuffer;
1415
1516template <typename T>
16- class DeleteRequest : public Request {
17+ class DeletableWrapper : public Deletable {
1718 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 ();
2126 }
2227
2328 private:
24- T* object_;
29+ std::unique_ptr<T> object_;
2530};
2631
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+ }
3137
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)) {}
3643
37- void Call () override {
38- Apply (target_, fn_, std::move (arg_ ));
44+ void Call (MainThreadInterface* thread) {
45+ thread-> AddObject (object_id_, WrapInDeletable ( factory_ (thread) ));
3946 }
4047
4148 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_);
4565 }
4666
47- Target* target_;
48- Fn fn_;
49- Arg arg_;
67+ private:
68+ int object_id_;
5069};
5170
52- class PostMessageRequest : public Request {
71+ template <typename Target, typename Fn>
72+ class CallRequest : public Request {
5373 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)) {}
5875
59- void Call () override {
60- delegate_-> SendMessageToFrontend (message_-> string ( ));
76+ void Call (MainThreadInterface* thread ) override {
77+ fn_ (DeletableWrapper<Target>:: get (thread, id_ ));
6178 }
6279
6380 private:
64- InspectorSessionDelegate* delegate_ ;
65- std::unique_ptr<StringBuffer> message_ ;
81+ int id_ ;
82+ Fn fn_ ;
6683};
6784
6885class DispatchMessagesTask : public v8 ::Task {
@@ -88,45 +105,63 @@ void DisposePairCallback(uv_handle_t* ref) {
88105template <typename T>
89106class AnotherThreadObjectReference {
90107 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)));
96117 }
97118 AnotherThreadObjectReference (AnotherThreadObjectReference&) = delete;
98119
99120 ~AnotherThreadObjectReference () {
100121 // 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_)));
104124 }
105125
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))));
110131 }
111132
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)));
114136 }
115137
116138 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+
117147 std::shared_ptr<MainThreadHandle> thread_;
118- T* object_ ;
148+ const int object_id_ ;
119149};
120150
121151class MainThreadSessionState {
122152 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+ }
127162
128163 void Connect (std::unique_ptr<InspectorSessionDelegate> delegate) {
129- Agent* agent = thread_->GetInspectorAgent ();
164+ Agent* agent = thread_->inspector_agent ();
130165 if (agent != nullptr )
131166 session_ = agent->Connect (std::move (delegate), prevent_shutdown_);
132167 }
@@ -136,7 +171,7 @@ class MainThreadSessionState {
136171 }
137172
138173 private:
139- std::shared_ptr<MainThreadHandle> thread_;
174+ MainThreadInterface* thread_;
140175 bool prevent_shutdown_;
141176 std::unique_ptr<InspectorSession> session_;
142177};
@@ -148,12 +183,14 @@ class CrossThreadInspectorSession : public InspectorSession {
148183 std::shared_ptr<MainThreadHandle> thread,
149184 std::unique_ptr<InspectorSessionDelegate> delegate,
150185 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));
153190 }
154191
155192 void Dispatch (const StringView& message) override {
156- state_.Post (&MainThreadSessionState::Dispatch,
193+ state_.Call (&MainThreadSessionState::Dispatch,
157194 StringBuffer::create (message));
158195 }
159196
@@ -163,13 +200,15 @@ class CrossThreadInspectorSession : public InspectorSession {
163200
164201class ThreadSafeDelegate : public InspectorSessionDelegate {
165202 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) {}
169205
170206 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+ });
173212 }
174213
175214 private:
@@ -252,7 +291,7 @@ void MainThreadInterface::DispatchMessages() {
252291 MessageQueue::value_type task;
253292 std::swap (dispatching_message_queue_.front (), task);
254293 dispatching_message_queue_.pop_front ();
255- task->Call ();
294+ task->Call (this );
256295 }
257296 } while (had_messages);
258297 dispatching_messages_ = false ;
@@ -264,6 +303,26 @@ std::shared_ptr<MainThreadHandle> MainThreadInterface::GetHandle() {
264303 return handle_;
265304}
266305
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+
267326std::unique_ptr<StringBuffer> Utf8ToStringView (const std::string& message) {
268327 icu::UnicodeString utf16 = icu::UnicodeString::fromUTF8 (
269328 icu::StringPiece (message.data (), message.length ()));
@@ -303,10 +362,12 @@ Agent* MainThreadHandle::GetInspectorAgent() {
303362}
304363
305364std::unique_ptr<InspectorSessionDelegate>
306- MainThreadHandle::MakeThreadSafeDelegate (
365+ MainThreadHandle::MakeDelegateThreadSafe (
307366 std::unique_ptr<InspectorSessionDelegate> delegate) {
367+ int id = newObjectId ();
368+ main_thread_->AddObject (id, WrapInDeletable (std::move (delegate)));
308369 return std::unique_ptr<InspectorSessionDelegate>(
309- new ThreadSafeDelegate (shared_from_this (), std::move (delegate) ));
370+ new ThreadSafeDelegate (shared_from_this (), id ));
310371}
311372
312373bool MainThreadHandle::Expired () {
0 commit comments