Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2020-07-03 17:42:45 +0300
committerJames M Snell <jasnell@gmail.com>2020-07-06 00:56:59 +0300
commitd4f69002b44c55d4db93c01d5468f79e48f46417 (patch)
tree83adddf219b2078fa02ae4c12ee0d2f87e849be2 /src/timer_wrap.cc
parente7dadd376ec535e56faf3be75fe23549bf13abc9 (diff)
src: add TimerWrap utility
Consolidate uv_timer_t boilerplate code into a shared utility. There are several places throughout the code where we use uv_timer_t internally (inspector, perf, quic), with some code duplication. This eliminates the duplicated code, ensures that cleanup occurs correctly, and simplifies use of the timers. Signed-off-by: James M Snell <jasnell@gmail.com> PR-URL: https://github.com/nodejs/node/pull/34186 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'src/timer_wrap.cc')
-rw-r--r--src/timer_wrap.cc94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/timer_wrap.cc b/src/timer_wrap.cc
new file mode 100644
index 00000000000..618c50c82e2
--- /dev/null
+++ b/src/timer_wrap.cc
@@ -0,0 +1,94 @@
+#include "env-inl.h"
+#include "memory_tracker-inl.h"
+#include "timer_wrap.h"
+#include "uv.h"
+
+namespace node {
+
+TimerWrap::TimerWrap(Environment* env, TimerCb fn, void* user_data)
+ : env_(env),
+ fn_(fn),
+ user_data_(user_data) {
+ uv_timer_init(env->event_loop(), &timer_);
+ timer_.data = this;
+}
+
+void TimerWrap::Stop(bool close) {
+ if (timer_.data == nullptr) return;
+ uv_timer_stop(&timer_);
+ if (LIKELY(close)) {
+ timer_.data = nullptr;
+ env_->CloseHandle(reinterpret_cast<uv_handle_t*>(&timer_), TimerClosedCb);
+ }
+}
+
+void TimerWrap::TimerClosedCb(uv_handle_t* handle) {
+ std::unique_ptr<TimerWrap> ptr(
+ ContainerOf(&TimerWrap::timer_,
+ reinterpret_cast<uv_timer_t*>(handle)));
+}
+
+void TimerWrap::Update(uint64_t interval, uint64_t repeat) {
+ if (timer_.data == nullptr) return;
+ uv_timer_start(&timer_, OnTimeout, interval, repeat);
+}
+
+void TimerWrap::Ref() {
+ if (timer_.data == nullptr) return;
+ uv_ref(reinterpret_cast<uv_handle_t*>(&timer_));
+}
+
+void TimerWrap::Unref() {
+ if (timer_.data == nullptr) return;
+ uv_unref(reinterpret_cast<uv_handle_t*>(&timer_));
+}
+
+void TimerWrap::OnTimeout(uv_timer_t* timer) {
+ TimerWrap* t = ContainerOf(&TimerWrap::timer_, timer);
+ t->fn_(t->user_data_);
+}
+
+TimerWrapHandle::TimerWrapHandle(
+ Environment* env,
+ TimerWrap::TimerCb fn,
+ void* user_data) {
+ timer_ = new TimerWrap(env, fn, user_data);
+ env->AddCleanupHook(CleanupHook, this);
+}
+
+void TimerWrapHandle::Stop(bool close) {
+ if (UNLIKELY(!close))
+ return timer_->Stop(close);
+
+ if (timer_ != nullptr) {
+ timer_->env()->RemoveCleanupHook(CleanupHook, this);
+ timer_->Stop();
+ }
+ timer_ = nullptr;
+}
+
+void TimerWrapHandle::Ref() {
+ if (timer_ != nullptr)
+ timer_->Ref();
+}
+
+void TimerWrapHandle::Unref() {
+ if (timer_ != nullptr)
+ timer_->Unref();
+}
+
+void TimerWrapHandle::Update(uint64_t interval, uint64_t repeat) {
+ if (timer_ != nullptr)
+ timer_->Update(interval, repeat);
+}
+
+void TimerWrapHandle::CleanupHook(void* data) {
+ static_cast<TimerWrapHandle*>(data)->Stop();
+}
+
+void TimerWrapHandle::MemoryInfo(node::MemoryTracker* tracker) const {
+ if (timer_ != nullptr)
+ tracker->TrackField("timer", *timer_);
+}
+
+} // namespace node