aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsimonb <simonb>2006-06-19 05:04:42 (GMT)
committersimonb <simonb>2006-06-19 05:04:42 (GMT)
commitf6140840f85e35354c219e3a505c6d1aeb4d3837 (patch)
tree64f7c645454f75a0a9d02f5befa7cd59d27321b3
parent3bce4aab734683f968d823ffa2d34a78a4babf93 (diff)
downloadfluxbox_pavel-f6140840f85e35354c219e3a505c6d1aeb4d3837.zip
fluxbox_pavel-f6140840f85e35354c219e3a505c6d1aeb4d3837.tar.bz2
fix timer issues (esp clock not updating on multiple screens)
-rw-r--r--ChangeLog5
-rw-r--r--src/ClockTool.cc5
-rw-r--r--src/FbTk/Timer.cc83
-rw-r--r--src/FbTk/Timer.hh14
4 files changed, 58 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index d7319a7..7a2b5f8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
1 (Format: Year/Month/Day) 1 (Format: Year/Month/Day)
2Changes for 1.0rc2: 2Changes for 1.0rc2:
3*06/06/19:
4 * Fix bug #1507671, clock not updating on multiple screens (Simon)
5 - time() and gettimeofday() are inconsistent, only use gettimeofday
6 - clean up Timer stuff a bit, fixed some other bugs
7 FbTk/Timer.hh/cc ClockTool.cc
3*06/06/18: 8*06/06/18:
4 * Fixed bug #1507754 iconbar text was not updated to match titlebar (Henrik) 9 * Fixed bug #1507754 iconbar text was not updated to match titlebar (Henrik)
5 WinClient.cc 10 WinClient.cc
diff --git a/src/ClockTool.cc b/src/ClockTool.cc
index 2c0ad46..efc0ffb 100644
--- a/src/ClockTool.cc
+++ b/src/ClockTool.cc
@@ -45,6 +45,7 @@
45#else 45#else
46 #include <time.h> 46 #include <time.h>
47#endif 47#endif
48#include <sys/time.h>
48#include <string> 49#include <string>
49#include <typeinfo> 50#include <typeinfo>
50 51
@@ -242,7 +243,9 @@ unsigned int ClockTool::height() const {
242 243
243void ClockTool::updateTime() { 244void ClockTool::updateTime() {
244 // update clock 245 // update clock
245 time_t the_time = time(0); 246 timeval now;
247 gettimeofday(&now, 0);
248 time_t the_time = now.tv_sec;
246 249
247 if (the_time != -1) { 250 if (the_time != -1) {
248 char time_string[255]; 251 char time_string[255];
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