diff options
Diffstat (limited to 'src/FbTk')
-rw-r--r-- | src/FbTk/Timer.cc | 83 | ||||
-rw-r--r-- | src/FbTk/Timer.hh | 14 |
2 files changed, 49 insertions, 48 deletions
diff --git a/src/FbTk/Timer.cc b/src/FbTk/Timer.cc index 15da0fb..9492ac6 100644 --- a/src/FbTk/Timer.cc +++ b/src/FbTk/Timer.cc | |||
@@ -98,6 +98,15 @@ void Timer::stop() { | |||
98 | removeTimer(this); //remove us from the list | 98 | removeTimer(this); //remove us from the list |
99 | } | 99 | } |
100 | 100 | ||
101 | void Timer::makeEndTime(timeval &tm) const { | ||
102 | tm.tv_sec = m_start.tv_sec + m_timeout.tv_sec; | ||
103 | tm.tv_usec = m_start.tv_usec + m_timeout.tv_usec; | ||
104 | if (tm.tv_usec >= 1000000) { | ||
105 | tm.tv_usec -= 1000000; | ||
106 | tm.tv_sec++; | ||
107 | } | ||
108 | } | ||
109 | |||
101 | 110 | ||
102 | void Timer::fireTimeout() { | 111 | void Timer::fireTimeout() { |
103 | if (*m_handler) | 112 | if (*m_handler) |
@@ -111,79 +120,69 @@ void Timer::updateTimers(int fd) { | |||
111 | FD_ZERO(&rfds); | 120 | FD_ZERO(&rfds); |
112 | FD_SET(fd, &rfds); | 121 | FD_SET(fd, &rfds); |
113 | 122 | ||
123 | bool overdue = false; | ||
114 | 124 | ||
115 | if (!m_timerlist.empty()) { | 125 | if (!m_timerlist.empty()) { |
116 | gettimeofday(&now, 0); | 126 | gettimeofday(&now, 0); |
117 | 127 | ||
118 | tm.tv_sec = tm.tv_usec = 0l; | ||
119 | |||
120 | Timer *timer = m_timerlist.front(); | 128 | Timer *timer = m_timerlist.front(); |
121 | 129 | ||
122 | const timeval &start = timer->getStartTime(); | 130 | timer->makeEndTime(tm); |
123 | const timeval &length = timer->getTimeout(); | ||
124 | tm.tv_sec = start.tv_sec + | ||
125 | length.tv_sec - now.tv_sec; | ||
126 | tm.tv_usec = start.tv_usec + | ||
127 | length.tv_usec - now.tv_usec; | ||
128 | 131 | ||
129 | while (tm.tv_usec >= 1000000) { | 132 | tm.tv_sec -= now.tv_sec; |
130 | tm.tv_sec++; | 133 | tm.tv_usec -= now.tv_usec; |
131 | tm.tv_usec -= 1000000; | ||
132 | } | ||
133 | 134 | ||
134 | while (tm.tv_usec < 0) { | 135 | while (tm.tv_usec < 0) { |
135 | if (tm.tv_sec > 0) { | 136 | if (tm.tv_sec > 0) { |
136 | tm.tv_sec--; | 137 | tm.tv_sec--; |
137 | tm.tv_usec += 1000000; | 138 | tm.tv_usec += 1000000; |
138 | } else { | 139 | } else { |
140 | overdue = true; | ||
139 | tm.tv_usec = 0; | 141 | tm.tv_usec = 0; |
140 | break; | 142 | break; |
141 | } | 143 | } |
142 | } | 144 | } |
143 | 145 | ||
144 | if (tm.tv_sec < 0) { | 146 | if (tm.tv_sec < 0) { // usec zero-ed above if negative |
145 | tm.tv_sec = 0; | 147 | tm.tv_sec = 0; |
146 | tm.tv_usec = 0; | 148 | tm.tv_usec = 0; |
149 | overdue = true; | ||
147 | } | 150 | } |
148 | 151 | ||
149 | timeout = &tm; | 152 | timeout = &tm; |
150 | } | 153 | } |
151 | 154 | ||
152 | if (select(fd + 1, &rfds, 0, 0, timeout) != 0) | 155 | if (!overdue && select(fd + 1, &rfds, 0, 0, timeout) != 0) |
153 | // didn't time out! x events pending | 156 | // didn't time out! x events pending |
154 | return; | 157 | return; |
155 | 158 | ||
156 | TimerList::iterator it; | 159 | TimerList::iterator it; |
157 | 160 | ||
161 | // check for timer timeout | ||
162 | gettimeofday(&now, 0); | ||
163 | |||
158 | // someone set the date of the machine BACK | 164 | // someone set the date of the machine BACK |
159 | // so we have to adjust the start_time | 165 | // so we have to adjust the start_time |
160 | static time_t last_time = time(0); | 166 | static time_t last_time = 0; |
161 | if (time(0) < last_time) { | 167 | if (now.tv_sec < last_time) { |
162 | 168 | ||
163 | time_t delta = time(0) - last_time; | 169 | time_t delta = last_time - now.tv_sec; |
164 | 170 | ||
165 | for (it = m_timerlist.begin(); it != m_timerlist.end(); it++) { | 171 | for (it = m_timerlist.begin(); it != m_timerlist.end(); it++) { |
166 | (*it)->m_start.tv_sec += delta; | 172 | (*it)->m_start.tv_sec -= delta; |
167 | } | 173 | } |
168 | } | 174 | } |
175 | last_time = now.tv_sec; | ||
169 | 176 | ||
170 | 177 | ||
171 | // check for timer timeout | ||
172 | gettimeofday(&now, 0); | ||
173 | |||
174 | //must check end ...the timer might remove | 178 | //must check end ...the timer might remove |
175 | //it self from the list (should be fixed in the future) | 179 | //it self from the list (should be fixed in the future) |
176 | for(it = m_timerlist.begin(); it != m_timerlist.end(); ) { | 180 | for(it = m_timerlist.begin(); it != m_timerlist.end(); ) { |
177 | //This is to make sure we don't get an invalid iterator | 181 | //This is to make sure we don't get an invalid iterator |
178 | //when we do fireTimeout | 182 | //when we do fireTimeout |
179 | Timer &t = *(*it); | 183 | Timer &t = *(*it); |
180 | const timeval &start = t.getStartTime(); | ||
181 | const timeval &length = t.getTimeout(); | ||
182 | 184 | ||
183 | tm.tv_sec = start.tv_sec + | 185 | t.makeEndTime(tm); |
184 | length.tv_sec; | ||
185 | tm.tv_usec = start.tv_usec + | ||
186 | length.tv_usec; | ||
187 | 186 | ||
188 | if (((now.tv_sec < tm.tv_sec) || | 187 | if (((now.tv_sec < tm.tv_sec) || |
189 | (now.tv_sec == tm.tv_sec && now.tv_usec < tm.tv_usec))) | 188 | (now.tv_sec == tm.tv_sec && now.tv_usec < tm.tv_usec))) |
@@ -192,15 +191,10 @@ void Timer::updateTimers(int fd) { | |||
192 | t.fireTimeout(); | 191 | t.fireTimeout(); |
193 | // restart the current timer so that the start time is updated | 192 | // restart the current timer so that the start time is updated |
194 | if (! t.doOnce()) { | 193 | if (! t.doOnce()) { |
195 | if (t.getInterval() != 0) { | 194 | // must erase so that it's put into the right place in the list |
196 | it = m_timerlist.erase(it); | 195 | it = m_timerlist.erase(it); |
197 | } | 196 | t.m_timing = false; |
198 | t.start(); | 197 | t.start(); |
199 | |||
200 | // Note that this mustn't be done if we're deleting the | ||
201 | // entry from the list, so therefore it's not in the update | ||
202 | // section of the for loop | ||
203 | it++; | ||
204 | } else { | 198 | } else { |
205 | // Since the default stop behaviour results in the timer | 199 | // Since the default stop behaviour results in the timer |
206 | // being removed, we must remove it here, so that the iterator | 200 | // being removed, we must remove it here, so that the iterator |
@@ -211,15 +205,14 @@ void Timer::updateTimers(int fd) { | |||
211 | } | 205 | } |
212 | } | 206 | } |
213 | 207 | ||
214 | last_time = time(0); | ||
215 | } | 208 | } |
216 | 209 | ||
217 | void Timer::addTimer(Timer *timer) { | 210 | void Timer::addTimer(Timer *timer) { |
218 | assert(timer); | 211 | assert(timer); |
219 | int interval = timer->getInterval(); | 212 | int interval = timer->getInterval(); |
220 | // interval timers have their timeout change every time they are started! | 213 | // interval timers have their timeout change every time they are started! |
214 | timeval tm; | ||
221 | if (interval != 0) { | 215 | if (interval != 0) { |
222 | timeval tm; | ||
223 | tm.tv_sec = timer->getStartTime().tv_sec; | 216 | tm.tv_sec = timer->getStartTime().tv_sec; |
224 | tm.tv_usec = timer->getStartTime().tv_usec; | 217 | tm.tv_usec = timer->getStartTime().tv_usec; |
225 | 218 | ||
@@ -233,13 +226,19 @@ void Timer::addTimer(Timer *timer) { | |||
233 | timer->setTimeout(tm); | 226 | timer->setTimeout(tm); |
234 | } | 227 | } |
235 | 228 | ||
229 | // set timeval to the time-of-trigger | ||
230 | timer->makeEndTime(tm); | ||
231 | |||
232 | // timer list is sorted by trigger time (i.e. start plus timeout) | ||
236 | TimerList::iterator it = m_timerlist.begin(); | 233 | TimerList::iterator it = m_timerlist.begin(); |
237 | TimerList::iterator it_end = m_timerlist.end(); | 234 | TimerList::iterator it_end = m_timerlist.end(); |
238 | int index = 0; | 235 | for (; it != it_end; ++it) { |
239 | for (; it != it_end; ++it, ++index) { | 236 | timeval trig; |
240 | if (((*it)->getTimeout().tv_sec > timer->getTimeout().tv_sec) || | 237 | (*it)->makeEndTime(trig); |
241 | (((*it)->getTimeout().tv_sec == timer->getTimeout().tv_sec) && | 238 | |
242 | ((*it)->getTimeout().tv_usec >= timer->getTimeout().tv_usec))) { | 239 | if ((trig.tv_sec > tm.tv_sec) || |
240 | (trig.tv_sec == tm.tv_sec && | ||
241 | trig.tv_usec >= tm.tv_usec)) { | ||
243 | break; | 242 | break; |
244 | } | 243 | } |
245 | } | 244 | } |
diff --git a/src/FbTk/Timer.hh b/src/FbTk/Timer.hh index 773d5b8..189c2af 100644 --- a/src/FbTk/Timer.hh +++ b/src/FbTk/Timer.hh | |||
@@ -74,12 +74,14 @@ public: | |||
74 | /// update all timers | 74 | /// update all timers |
75 | static void updateTimers(int file_descriptor); | 75 | static void updateTimers(int file_descriptor); |
76 | 76 | ||
77 | inline int isTiming() const { return m_timing; } | 77 | int isTiming() const { return m_timing; } |
78 | inline int getInterval() const { return m_interval; } | 78 | int getInterval() const { return m_interval; } |
79 | inline int doOnce() const { return m_once; } | ||
80 | 79 | ||
81 | inline const timeval &getTimeout() const { return m_timeout; } | 80 | int doOnce() const { return m_once; } |
82 | inline const timeval &getStartTime() const { return m_start; } | 81 | |
82 | const timeval &getTimeout() const { return m_timeout; } | ||
83 | const timeval &getStartTime() const { return m_start; } | ||
84 | void makeEndTime(timeval &tm) const; | ||
83 | 85 | ||
84 | protected: | 86 | protected: |
85 | /// force a timeout | 87 | /// force a timeout |
@@ -92,7 +94,7 @@ private: | |||
92 | static void removeTimer(Timer *timer); | 94 | static void removeTimer(Timer *timer); |
93 | 95 | ||
94 | typedef std::list<Timer *> TimerList; | 96 | typedef std::list<Timer *> TimerList; |
95 | static TimerList m_timerlist; ///< list of all timers | 97 | static TimerList m_timerlist; ///< list of all timers, sorted by next trigger time (start + timeout) |
96 | 98 | ||
97 | RefCount<Command> m_handler; ///< what to do on a timeout | 99 | RefCount<Command> m_handler; ///< what to do on a timeout |
98 | 100 | ||