From 012206e92dafa216d4082c5991d5599dc504cb50 Mon Sep 17 00:00:00 2001 From: Eugene Ostroukhov Date: Mon, 17 Jul 2017 17:08:46 -0700 Subject: [PATCH] inspector: implement V8Inspector timer This timer is currently only used by a profiler. Note that the timer invocation will not interrupt JavaScript code. Fixes: https://github.com/nodejs/node/issues/11401 PR-URL: https://github.com/nodejs/node/pull/14346 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Ben Noordhuis --- src/inspector_agent.cc | 74 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index a06ff032ff7d51..6599e870432662 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -12,6 +12,7 @@ #include "libplatform/libplatform.h" #include +#include #include #ifdef __POSIX__ @@ -39,6 +40,7 @@ using v8::Value; using v8_inspector::StringBuffer; using v8_inspector::StringView; using v8_inspector::V8Inspector; +using v8_inspector::V8InspectorClient; static uv_sem_t start_io_thread_semaphore; static uv_async_t start_io_thread_async; @@ -429,9 +431,66 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel { std::unique_ptr session_; }; +class InspectorTimer { + public: + InspectorTimer(uv_loop_t* loop, + double interval_s, + V8InspectorClient::TimerCallback callback, + void* data) : timer_(), + callback_(callback), + data_(data) { + uv_timer_init(loop, &timer_); + int64_t interval_ms = 1000 * interval_s; + uv_timer_start(&timer_, OnTimer, interval_ms, interval_ms); + } + + InspectorTimer(const InspectorTimer&) = delete; + + void Stop() { + uv_timer_stop(&timer_); + uv_close(reinterpret_cast(&timer_), TimerClosedCb); + } + + private: + static void OnTimer(uv_timer_t* uvtimer) { + InspectorTimer* timer = node::ContainerOf(&InspectorTimer::timer_, uvtimer); + timer->callback_(timer->data_); + } + + static void TimerClosedCb(uv_handle_t* uvtimer) { + InspectorTimer* timer = + node::ContainerOf(&InspectorTimer::timer_, + reinterpret_cast(uvtimer)); + delete timer; + } + + ~InspectorTimer() {} + + uv_timer_t timer_; + V8InspectorClient::TimerCallback callback_; + void* data_; +}; + +class InspectorTimerHandle { + public: + InspectorTimerHandle(uv_loop_t* loop, double interval_s, + V8InspectorClient::TimerCallback callback, void* data) { + timer_ = new InspectorTimer(loop, interval_s, callback, data); + } + + InspectorTimerHandle(const InspectorTimerHandle&) = delete; + + ~InspectorTimerHandle() { + CHECK_NE(timer_, nullptr); + timer_->Stop(); + timer_ = nullptr; + } + private: + InspectorTimer* timer_; +}; } // namespace -class NodeInspectorClient : public v8_inspector::V8InspectorClient { +class NodeInspectorClient : public V8InspectorClient { public: NodeInspectorClient(node::Environment* env, v8::Platform* platform) : env_(env), @@ -527,6 +586,18 @@ class NodeInspectorClient : public v8_inspector::V8InspectorClient { return channel_.get(); } + void startRepeatingTimer(double interval_s, + TimerCallback callback, + void* data) override { + timers_.emplace(std::piecewise_construct, std::make_tuple(data), + std::make_tuple(env_->event_loop(), interval_s, callback, + data)); + } + + void cancelTimer(void* data) override { + timers_.erase(data); + } + private: node::Environment* env_; v8::Platform* platform_; @@ -534,6 +605,7 @@ class NodeInspectorClient : public v8_inspector::V8InspectorClient { bool running_nested_loop_; std::unique_ptr client_; std::unique_ptr channel_; + std::unordered_map timers_; }; Agent::Agent(Environment* env) : parent_env_(env),