aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk')
-rw-r--r--src/FbTk/Timer.cc83
-rw-r--r--src/FbTk/Timer.hh14
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
101void 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
102void Timer::fireTimeout() { 111void 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
217void Timer::addTimer(Timer *timer) { 210void 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
84protected: 86protected:
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