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:
-rw-r--r--node.gyp2
-rw-r--r--src/timer_wrap.cc94
-rw-r--r--src/timer_wrap.h84
3 files changed, 180 insertions, 0 deletions
diff --git a/node.gyp b/node.gyp
index 47ce95de755..23f9e2ec7ff 100644
--- a/node.gyp
+++ b/node.gyp
@@ -638,6 +638,7 @@
'src/string_decoder.cc',
'src/tcp_wrap.cc',
'src/timers.cc',
+ 'src/timer_wrap.cc',
'src/tracing/agent.cc',
'src/tracing/node_trace_buffer.cc',
'src/tracing/node_trace_writer.cc',
@@ -741,6 +742,7 @@
'src/tracing/trace_event.h',
'src/tracing/trace_event_common.h',
'src/tracing/traced_value.h',
+ 'src/timer_wrap.h',
'src/tty_wrap.h',
'src/udp_wrap.h',
'src/util.h',
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
diff --git a/src/timer_wrap.h b/src/timer_wrap.h
new file mode 100644
index 00000000000..c75e17b776b
--- /dev/null
+++ b/src/timer_wrap.h
@@ -0,0 +1,84 @@
+#ifndef SRC_TIMER_WRAP_H_
+#define SRC_TIMER_WRAP_H_
+
+#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
+
+#include "memory_tracker.h"
+#include "env.h"
+#include "uv.h"
+
+#include <functional>
+
+namespace node {
+
+// Utility class that makes working with libuv timers a bit easier.
+class TimerWrap final : public MemoryRetainer {
+ public:
+ using TimerCb = std::function<void(void*)>;
+
+ TimerWrap(Environment* env, TimerCb fn, void* user_data);
+ TimerWrap(const TimerWrap&) = delete;
+
+ inline Environment* env() const { return env_; }
+
+ // Completely stops the timer, making it no longer usable.
+ void Stop(bool close = true);
+
+ // Starts / Restarts the Timer
+ void Update(uint64_t interval, uint64_t repeat = 0);
+
+ void Ref();
+
+ void Unref();
+
+ SET_NO_MEMORY_INFO();
+ SET_MEMORY_INFO_NAME(TimerWrap)
+ SET_SELF_SIZE(TimerWrap)
+
+ private:
+ static void TimerClosedCb(uv_handle_t* handle);
+ static void OnTimeout(uv_timer_t* timer);
+ ~TimerWrap() = default;
+
+ Environment* env_;
+ TimerCb fn_;
+ uv_timer_t timer_;
+ void* user_data_ = nullptr;
+
+ friend std::unique_ptr<TimerWrap>::deleter_type;
+};
+
+class TimerWrapHandle : public MemoryRetainer {
+ public:
+ TimerWrapHandle(
+ Environment* env,
+ TimerWrap::TimerCb fn,
+ void* user_data = nullptr);
+
+ TimerWrapHandle(const TimerWrapHandle&) = delete;
+
+ ~TimerWrapHandle() { Stop(); }
+
+ void Update(uint64_t interval, uint64_t repeat = 0);
+
+ void Ref();
+
+ void Unref();
+
+ void Stop(bool close = true);
+
+ void MemoryInfo(node::MemoryTracker* tracker) const override;
+
+ SET_MEMORY_INFO_NAME(TimerWrapHandle)
+ SET_SELF_SIZE(TimerWrapHandle)
+
+ private:
+ static void CleanupHook(void* data);
+ TimerWrap* timer_;
+};
+
+} // namespace node
+
+#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
+
+#endif // SRC_TIMER_WRAP_H_