-
Notifications
You must be signed in to change notification settings - Fork 0
/
Timer.cpp
136 lines (116 loc) · 2.93 KB
/
Timer.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
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <list>
#include "Timer.h"
using namespace std;
std::list<Timer*>Timer::pTimers;
bool Timer::initialized = false;
void Timer::createTimer(int32_t timeout_ms, bool _periodic, TimerExpired TimerCallback, void *data)
{
static struct sigaction sa;
static struct itimerval timer;
timeout = timeout_ms;
periodic = _periodic;
callback = TimerCallback;
setData(data);
current = timeout_ms;
if (initialized)
{
pTimers.push_back(this);
return;
}
pTimers.push_back(this);
running = false;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGALRM, &sa, NULL);
/* Configure the timer to expire after 250 msec... */
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 1000;
/* ... and every 250 msec after that. */
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 1000;
initialized = true;
setitimer (ITIMER_REAL, &timer, NULL);
}
Timer::Timer()
{
createTimer(1000, false, NULL, NULL);
}
Timer::Timer(int32_t timeout_ms, bool _periodic, TimerExpired TimerCallback, void *data)
{
createTimer(timeout_ms, _periodic, TimerCallback, data);
}
void Timer::stop()
{
running = false;
current = timeout;
}
void Timer::setData(void *data)
{
if (data == NULL)
{
data = this;
}
pData = data;
}
void Timer::setInterval(int32_t timeout_ms)
{
timeout = timeout_ms;
current = timeout;
}
void Timer::timer_handler (int signum)
{
std::list<Timer*>::iterator it;
std::list<Timer*>callbackList;
// Note: We need 3 loops because calling the callback
// might cause the timer to delete itself, which
// would cause the iterator to fail. So, we
// collect callbacks to call, then call them, then
// maintain the timers.
// Find callbacks to call
for(it = Timer::pTimers.begin(); it != Timer::pTimers.end(); it++)
{
Timer* pTimer = *it;
if (pTimer->running)
{
pTimer->current--;
if(pTimer->current == 0)
{
if (pTimer->callback)
{
callbackList.push_back(pTimer);
}
}
}
}
// Call the callbacks
for(it = callbackList.begin(); it != callbackList.end(); it++)
{
Timer* pTimer = *it;
pTimer->callback(pTimer->pData);
}
// maintain the timers
for(it = Timer::pTimers.begin(); it != Timer::pTimers.end(); it++)
{
Timer* pTimer = *it;
if (pTimer->running)
{
// The loop above may have cause current to be zero, so check it
if(pTimer->current == 0)
{
if (pTimer->periodic)
{
pTimer->current = pTimer->timeout;
}
else
{
pTimer->running = false;
}
}
}
}
}