-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwdt.hpp
114 lines (92 loc) · 2.42 KB
/
wdt.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#pragma once
#ifndef WATCHDOGTIMER_CLASS_H
#define WATCHDOGTIMER_CLASS_H
#include <chrono>
#include <thread>
#include <atomic>
#include <condition_variable>
#include <functional>
template<typename Clock>
class BaseWatchdogTimer
{
public:
typedef std::chrono::milliseconds Milliseconds;
private:
std::mutex mutex;
std::condition_variable loop_condition;
std::atomic_bool loop_flag;
std::thread loop_thread;
private:
typename Clock::time_point clock_counter;
private:
BaseWatchdogTimer(const BaseWatchdogTimer<Clock>&) = delete;
BaseWatchdogTimer(BaseWatchdogTimer<Clock>&&) = delete;
BaseWatchdogTimer<Clock>& operator=(const BaseWatchdogTimer<Clock>&) = delete;
BaseWatchdogTimer<Clock>& operator=(BaseWatchdogTimer<Clock>&&) = delete;
private:
void forever(Milliseconds timeout, bool loop)
{
std::unique_lock<std::mutex> lock(this->mutex);
do
{
do
{
// 'std::condition_variable::wait_for' may return no_timeout although time exceeds timeout
// So, must use another variable like 'loop_flag'
if (this->loop_condition.wait_for(lock, timeout, [=]() {return !this->loop_flag.load(); }))
{
if (!this->loop_flag)
goto out;
}
} while (std::chrono::duration_cast<Milliseconds>((Clock::now() - this->clock_counter)) < timeout);
this->on_timeout();
} while (loop);
out:
return;
}
public:
std::function<void(void)> on_timeout_callback;
private:
virtual void on_timeout()
{
if (on_timeout_callback)
on_timeout_callback();
}
public:
BaseWatchdogTimer()
{
}
virtual ~BaseWatchdogTimer()
{
stop();
}
public:
void kick(unsigned int timeout_ms, bool loop = false)
{
kick(Milliseconds(timeout_ms), loop);
}
void kick(Milliseconds timeout, bool loop = false)
{
stop();
loop_flag = true;
loop_thread = std::thread(std::bind(&BaseWatchdogTimer<Clock>::forever, this, timeout, loop));
}
void clear()
{
this->clock_counter = Clock::now();
}
void stop()
{
loop_flag = false;
loop_condition.notify_all();
if (loop_thread.joinable() && loop_thread.get_id() != std::this_thread::get_id())
loop_thread.join();
}
};
typedef std::chrono::high_resolution_clock HighResolutionClock;
typedef std::chrono::system_clock SystemClock;
typedef HighResolutionClock DefaultClock;
typedef BaseWatchdogTimer<HighResolutionClock> HighResolutionWatchdogTimer;
typedef BaseWatchdogTimer<SystemClock> SystemClockWatchdogTimer;
typedef BaseWatchdogTimer<DefaultClock> WatchdogTimer;
#endif