Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
watchdog.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <chrono>
4#include <functional>
5#include <thread>
6#include <mutex>
7#include <condition_variable>
8
9namespace sysio { namespace vm {
10
13 class watchdog {
14 class guard;
15 public:
18 template <typename TimeUnits>
19 explicit watchdog(const TimeUnits& duration) : _duration(duration) {}
25 template<typename F>
26 [[nodiscard]] guard scoped_run(F&& callback) {
27 return guard(_duration, static_cast<F&&>(callback));
28 }
29
30 private:
31 class guard {
32 public:
33 guard(const guard&) = delete;
34 guard& operator=(const guard&) = delete;
35
36 template <typename TimeUnits, typename F>
37 guard(const TimeUnits& duration, F&& callback)
38 : _callback(static_cast<F&&>(callback)),
39 _run_state(running),
40 _duration(duration),
41 _start(std::chrono::steady_clock::now()) {
42 // Must be started after all other initialization to avoid races.
43 _timer = std::thread(&guard::runner, this);
44 }
45 ~guard() {
46 {
47 auto _lock = std::unique_lock(_mutex);
48 _run_state = stopped;
49 }
50 _cond.notify_one();
51 _timer.join();
52 }
53
54 private:
55 // worker thread
56 // Implementation notes: This implementation creates a thread for
57 // each watchdog. If there are many watchdogs, it might be more
58 // efficient to create a single thread for them all.
59 void runner() {
60 auto _lock = std::unique_lock(_mutex);
61 // wait until the timer expires or someone stops it.
62 _cond.wait_until(_lock, _start + _duration, [&]() { return _run_state != running; });
63 if (_run_state == running) {
64 _run_state = interrupted;
65 _callback();
66 }
67 }
68 enum state_t { running, interrupted, stopped };
69 using time_point_type = std::chrono::time_point<std::chrono::steady_clock>;
70 using duration_type = std::chrono::steady_clock::duration;
71 std::thread _timer;
72 std::mutex _mutex;
73 std::condition_variable _cond;
74 std::function<void()> _callback;
75 state_t _run_state = stopped;
76 duration_type _duration;
77 time_point_type _start;
78 };
79 std::chrono::steady_clock::duration _duration;
80 };
81
83 public:
84 template<typename F>
85 null_watchdog scoped_run(F&&) { return *this; }
86 ~null_watchdog() {} // avoid unused variable warnings
87 };
88
89}} // namespace sysio::vm
null_watchdog scoped_run(F &&)
Definition watchdog.hpp:85
Triggers a callback after a given time elapses.
Definition watchdog.hpp:13
guard scoped_run(F &&callback)
Definition watchdog.hpp:26
watchdog(const TimeUnits &duration)
Definition watchdog.hpp:19
Definition name.hpp:106