diff options
Diffstat (limited to 'src/FbTk/Timer.cc')
-rw-r--r-- | src/FbTk/Timer.cc | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/src/FbTk/Timer.cc b/src/FbTk/Timer.cc index 09bb7dd..15da0fb 100644 --- a/src/FbTk/Timer.cc +++ b/src/FbTk/Timer.cc | |||
@@ -48,14 +48,15 @@ namespace FbTk { | |||
48 | 48 | ||
49 | Timer::TimerList Timer::m_timerlist; | 49 | Timer::TimerList Timer::m_timerlist; |
50 | 50 | ||
51 | Timer::Timer():m_timing(false), m_once(false) { | 51 | Timer::Timer():m_timing(false), m_once(false), m_interval(0) { |
52 | 52 | ||
53 | } | 53 | } |
54 | 54 | ||
55 | Timer::Timer(RefCount<Command> &handler): | 55 | Timer::Timer(RefCount<Command> &handler): |
56 | m_handler(handler), | 56 | m_handler(handler), |
57 | m_timing(false), | 57 | m_timing(false), |
58 | m_once(false) { | 58 | m_once(false), |
59 | m_interval(0) { | ||
59 | } | 60 | } |
60 | 61 | ||
61 | 62 | ||
@@ -72,7 +73,7 @@ void Timer::setTimeout(time_t t) { | |||
72 | } | 73 | } |
73 | 74 | ||
74 | 75 | ||
75 | void Timer::setTimeout(timeval t) { | 76 | void Timer::setTimeout(const timeval &t) { |
76 | m_timeout.tv_sec = t.tv_sec; | 77 | m_timeout.tv_sec = t.tv_sec; |
77 | m_timeout.tv_usec = t.tv_usec; | 78 | m_timeout.tv_usec = t.tv_usec; |
78 | } | 79 | } |
@@ -85,10 +86,10 @@ void Timer::start() { | |||
85 | gettimeofday(&m_start, 0); | 86 | gettimeofday(&m_start, 0); |
86 | 87 | ||
87 | // only add Timers that actually DO something | 88 | // only add Timers that actually DO something |
88 | if (! m_timing && *m_handler) { | 89 | if ((! m_timing || m_interval != 0) && *m_handler) { |
89 | m_timing = true; | 90 | m_timing = true; |
90 | addTimer(this); //add us to the list | 91 | addTimer(this); //add us to the list |
91 | } | 92 | } |
92 | } | 93 | } |
93 | 94 | ||
94 | 95 | ||
@@ -111,17 +112,19 @@ void Timer::updateTimers(int fd) { | |||
111 | FD_SET(fd, &rfds); | 112 | FD_SET(fd, &rfds); |
112 | 113 | ||
113 | 114 | ||
114 | if (m_timerlist.size() > 0) { | 115 | if (!m_timerlist.empty()) { |
115 | gettimeofday(&now, 0); | 116 | gettimeofday(&now, 0); |
116 | 117 | ||
117 | tm.tv_sec = tm.tv_usec = 0l; | 118 | tm.tv_sec = tm.tv_usec = 0l; |
118 | 119 | ||
119 | Timer *timer = m_timerlist.front(); | 120 | Timer *timer = m_timerlist.front(); |
120 | 121 | ||
121 | tm.tv_sec = timer->getStartTime().tv_sec + | 122 | const timeval &start = timer->getStartTime(); |
122 | timer->getTimeout().tv_sec - now.tv_sec; | 123 | const timeval &length = timer->getTimeout(); |
123 | tm.tv_usec = timer->getStartTime().tv_usec + | 124 | tm.tv_sec = start.tv_sec + |
124 | timer->getTimeout().tv_usec - now.tv_usec; | 125 | length.tv_sec - now.tv_sec; |
126 | tm.tv_usec = start.tv_usec + | ||
127 | length.tv_usec - now.tv_usec; | ||
125 | 128 | ||
126 | while (tm.tv_usec >= 1000000) { | 129 | while (tm.tv_usec >= 1000000) { |
127 | tm.tv_sec++; | 130 | tm.tv_sec++; |
@@ -138,10 +141,17 @@ void Timer::updateTimers(int fd) { | |||
138 | } | 141 | } |
139 | } | 142 | } |
140 | 143 | ||
144 | if (tm.tv_sec < 0) { | ||
145 | tm.tv_sec = 0; | ||
146 | tm.tv_usec = 0; | ||
147 | } | ||
148 | |||
141 | timeout = &tm; | 149 | timeout = &tm; |
142 | } | 150 | } |
143 | 151 | ||
144 | select(fd + 1, &rfds, 0, 0, timeout); | 152 | if (select(fd + 1, &rfds, 0, 0, timeout) != 0) |
153 | // didn't time out! x events pending | ||
154 | return; | ||
145 | 155 | ||
146 | TimerList::iterator it; | 156 | TimerList::iterator it; |
147 | 157 | ||
@@ -167,10 +177,13 @@ void Timer::updateTimers(int fd) { | |||
167 | //This is to make sure we don't get an invalid iterator | 177 | //This is to make sure we don't get an invalid iterator |
168 | //when we do fireTimeout | 178 | //when we do fireTimeout |
169 | Timer &t = *(*it); | 179 | Timer &t = *(*it); |
170 | tm.tv_sec = t.getStartTime().tv_sec + | 180 | const timeval &start = t.getStartTime(); |
171 | t.getTimeout().tv_sec; | 181 | const timeval &length = t.getTimeout(); |
172 | tm.tv_usec = t.getStartTime().tv_usec + | 182 | |
173 | t.getTimeout().tv_usec; | 183 | tm.tv_sec = start.tv_sec + |
184 | length.tv_sec; | ||
185 | tm.tv_usec = start.tv_usec + | ||
186 | length.tv_usec; | ||
174 | 187 | ||
175 | if (((now.tv_sec < tm.tv_sec) || | 188 | if (((now.tv_sec < tm.tv_sec) || |
176 | (now.tv_sec == tm.tv_sec && now.tv_usec < tm.tv_usec))) | 189 | (now.tv_sec == tm.tv_sec && now.tv_usec < tm.tv_usec))) |
@@ -179,6 +192,9 @@ void Timer::updateTimers(int fd) { | |||
179 | t.fireTimeout(); | 192 | t.fireTimeout(); |
180 | // restart the current timer so that the start time is updated | 193 | // restart the current timer so that the start time is updated |
181 | if (! t.doOnce()) { | 194 | if (! t.doOnce()) { |
195 | if (t.getInterval() != 0) { | ||
196 | it = m_timerlist.erase(it); | ||
197 | } | ||
182 | t.start(); | 198 | t.start(); |
183 | 199 | ||
184 | // Note that this mustn't be done if we're deleting the | 200 | // Note that this mustn't be done if we're deleting the |
@@ -200,6 +216,22 @@ void Timer::updateTimers(int fd) { | |||
200 | 216 | ||
201 | void Timer::addTimer(Timer *timer) { | 217 | void Timer::addTimer(Timer *timer) { |
202 | assert(timer); | 218 | assert(timer); |
219 | int interval = timer->getInterval(); | ||
220 | // interval timers have their timeout change every time they are started! | ||
221 | if (interval != 0) { | ||
222 | timeval tm; | ||
223 | tm.tv_sec = timer->getStartTime().tv_sec; | ||
224 | tm.tv_usec = timer->getStartTime().tv_usec; | ||
225 | |||
226 | // now convert to interval | ||
227 | tm.tv_sec = interval - (tm.tv_sec % interval) - 1; | ||
228 | tm.tv_usec = 1000000 - tm.tv_usec; | ||
229 | if (tm.tv_usec == 1000000) { | ||
230 | tm.tv_usec = 0; | ||
231 | tm.tv_sec += 1; | ||
232 | } | ||
233 | timer->setTimeout(tm); | ||
234 | } | ||
203 | 235 | ||
204 | TimerList::iterator it = m_timerlist.begin(); | 236 | TimerList::iterator it = m_timerlist.begin(); |
205 | TimerList::iterator it_end = m_timerlist.end(); | 237 | TimerList::iterator it_end = m_timerlist.end(); |