-
Notifications
You must be signed in to change notification settings - Fork 31
/
PeriodicTimer.cpp
62 lines (56 loc) · 1.83 KB
/
PeriodicTimer.cpp
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
#include "PeriodicTimer.hpp"
namespace msp {
PeriodicTimer::PeriodicTimer(std::function<void()> funct,
const double period_seconds) :
funct(funct) {
period_us =
std::chrono::duration<size_t, std::micro>(size_t(period_seconds * 1e6));
}
bool PeriodicTimer::start() {
// only start thread if period is above 0
if(!(period_us.count() > 0)) return false;
// only start once
if(running_.test_and_set()) return false;
// lock mutex so that the try_lock_until in the new thread always times out
// and loops
mutex_timer.lock();
// start the thread
thread_ptr = std::shared_ptr<std::thread>(new std::thread([this] {
// log now.
tstart = std::chrono::steady_clock::now();
while(true) {
// call function
funct();
// increment the reference time to know when to timeout waiting
tstart += period_us;
// wait until end of period or stop is called
if(mutex_timer.try_lock_until(tstart)) {
// gets here if lock was acquired (means someone called stop and
// manually unlocked the mutex)
mutex_timer.unlock();
break;
}
} // function over, return
}));
return true;
}
bool PeriodicTimer::stop() {
bool rc = false;
if(running_.test_and_set()) {
// was already running, so let the thread finish
mutex_timer.unlock();
if(thread_ptr != nullptr && thread_ptr->joinable()) {
thread_ptr->join();
}
rc = true;
}
running_.clear();
return rc;
}
void PeriodicTimer::setPeriod(const double& period_seconds) {
stop();
period_us =
std::chrono::duration<size_t, std::micro>(size_t(period_seconds * 1e6));
start();
}
} // namespace msp