diff options
Diffstat (limited to 'src/Timer.cc')
-rw-r--r-- | src/Timer.cc | 158 |
1 files changed, 126 insertions, 32 deletions
diff --git a/src/Timer.cc b/src/Timer.cc index f35f274..2c981d3 100644 --- a/src/Timer.cc +++ b/src/Timer.cc | |||
@@ -19,64 +19,158 @@ | |||
19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 19 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
20 | // DEALINGS IN THE SOFTWARE. | 20 | // DEALINGS IN THE SOFTWARE. |
21 | 21 | ||
22 | // stupid macros needed to access some functions in version 2 of the GNU C | 22 | #include "Timer.hh" |
23 | // library | 23 | |
24 | #ifndef _GNU_SOURCE | 24 | //use GNU extensions |
25 | # define _GNU_SOURCE | 25 | #ifndef _GNU_SOURCE |
26 | #define _GNU_SOURCE | ||
26 | #endif // _GNU_SOURCE | 27 | #endif // _GNU_SOURCE |
27 | 28 | ||
28 | #ifdef HAVE_CONFIG_H | 29 | #ifdef HAVE_CONFIG_H |
29 | # include "../config.h" | 30 | #include "../config.h" |
30 | #endif // HAVE_CONFIG_H | 31 | #endif // HAVE_CONFIG_H |
31 | 32 | ||
32 | #include "BaseDisplay.hh" | 33 | #include <sys/types.h> |
33 | #include "Timer.hh" | 34 | #include <unistd.h> |
35 | #include <cassert> | ||
34 | 36 | ||
37 | //static var | ||
38 | BTimer::TimerList BTimer::m_timerlist; | ||
35 | 39 | ||
36 | BTimer::BTimer(BaseDisplay *d, TimeoutHandler *h) { | 40 | BTimer::BTimer(TimeoutHandler *h): |
37 | display = d; | 41 | m_handler(h), |
38 | handler = h; | 42 | m_timing(false), |
39 | 43 | m_once(false) { | |
40 | once = timing = False; | ||
41 | } | 44 | } |
42 | 45 | ||
43 | 46 | ||
44 | BTimer::~BTimer(void) { | 47 | BTimer::~BTimer() { |
45 | if (timing) stop(); | 48 | if (isTiming()) stop(); |
46 | } | 49 | } |
47 | 50 | ||
48 | 51 | ||
49 | void BTimer::setTimeout(long t) { | 52 | void BTimer::setTimeout(long t) { |
50 | _timeout.tv_sec = t / 1000; | 53 | m_timeout.tv_sec = t / 1000; |
51 | _timeout.tv_usec = t; | 54 | m_timeout.tv_usec = t; |
52 | _timeout.tv_usec -= (_timeout.tv_sec * 1000); | 55 | m_timeout.tv_usec -= (m_timeout.tv_sec * 1000); |
53 | _timeout.tv_usec *= 1000; | 56 | m_timeout.tv_usec *= 1000; |
54 | } | 57 | } |
55 | 58 | ||
56 | 59 | ||
57 | void BTimer::setTimeout(timeval t) { | 60 | void BTimer::setTimeout(timeval t) { |
58 | _timeout.tv_sec = t.tv_sec; | 61 | m_timeout.tv_sec = t.tv_sec; |
59 | _timeout.tv_usec = t.tv_usec; | 62 | m_timeout.tv_usec = t.tv_usec; |
60 | } | 63 | } |
61 | 64 | ||
62 | 65 | ||
63 | void BTimer::start(void) { | 66 | void BTimer::start() { |
64 | gettimeofday(&_start, 0); | 67 | gettimeofday(&m_start, 0); |
68 | |||
69 | if (! m_timing) { | ||
70 | m_timing = true; | ||
71 | addTimer(this); //add us to the list | ||
72 | } | ||
73 | } | ||
74 | |||
65 | 75 | ||
66 | if (! timing) { | 76 | void BTimer::stop() { |
67 | timing = True; | 77 | m_timing = false; |
68 | display->addTimer(this); | 78 | removeTimer(this); //remove us from the list |
69 | } | ||
70 | } | 79 | } |
71 | 80 | ||
72 | 81 | ||
73 | void BTimer::stop(void) { | 82 | void BTimer::fireTimeout() { |
74 | timing = False; | 83 | if (m_handler) m_handler->timeout(); |
84 | } | ||
75 | 85 | ||
76 | display->removeTimer(this); | 86 | void BTimer::updateTimers(int fd) { |
87 | fd_set rfds; | ||
88 | timeval now, tm, *timeout = 0; | ||
89 | |||
90 | FD_ZERO(&rfds); | ||
91 | FD_SET(fd, &rfds); | ||
92 | |||
93 | if (m_timerlist.size() > 0) { | ||
94 | gettimeofday(&now, 0); | ||
95 | |||
96 | tm.tv_sec = tm.tv_usec = 0l; | ||
97 | |||
98 | BTimer *timer = m_timerlist.front(); | ||
99 | |||
100 | tm.tv_sec = timer->getStartTime().tv_sec + | ||
101 | timer->getTimeout().tv_sec - now.tv_sec; | ||
102 | tm.tv_usec = timer->getStartTime().tv_usec + | ||
103 | timer->getTimeout().tv_usec - now.tv_usec; | ||
104 | |||
105 | while (tm.tv_usec >= 1000000) { | ||
106 | tm.tv_sec++; | ||
107 | tm.tv_usec -= 1000000; | ||
108 | } | ||
109 | |||
110 | while (tm.tv_usec < 0) { | ||
111 | if (tm.tv_sec > 0) { | ||
112 | tm.tv_sec--; | ||
113 | tm.tv_usec += 1000000; | ||
114 | } else { | ||
115 | tm.tv_usec = 0; | ||
116 | break; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | timeout = &tm; | ||
121 | } | ||
122 | |||
123 | select(fd + 1, &rfds, 0, 0, timeout); | ||
124 | |||
125 | // check for timer timeout | ||
126 | gettimeofday(&now, 0); | ||
127 | |||
128 | TimerList::iterator it = m_timerlist.begin(); | ||
129 | //must check end ...the timer might remove | ||
130 | //it self from the list (should be fixed in the future) | ||
131 | for(; it != m_timerlist.end(); ++it) { | ||
132 | //This is to make sure we don't get an invalid iterator | ||
133 | //when we do fireTimeout | ||
134 | BTimer &t = *(*it); | ||
135 | tm.tv_sec = t.getStartTime().tv_sec + | ||
136 | t.getTimeout().tv_sec; | ||
137 | tm.tv_usec = t.getStartTime().tv_usec + | ||
138 | t.getTimeout().tv_usec; | ||
139 | |||
140 | if ((now.tv_sec < tm.tv_sec) || | ||
141 | (now.tv_sec == tm.tv_sec && now.tv_usec < tm.tv_usec)) | ||
142 | break; | ||
143 | |||
144 | t.fireTimeout(); | ||
145 | // restart the current timer so that the start time is updated | ||
146 | if (! t.doOnce()) | ||
147 | t.start(); | ||
148 | else { | ||
149 | t.stop(); | ||
150 | it--; | ||
151 | } | ||
152 | } | ||
77 | } | 153 | } |
78 | 154 | ||
155 | void BTimer::addTimer(BTimer *timer) { | ||
156 | assert(timer); | ||
157 | |||
158 | TimerList::iterator it = m_timerlist.begin(); | ||
159 | TimerList::iterator it_end = m_timerlist.end(); | ||
160 | int index = 0; | ||
161 | for (; it != it_end; ++it, ++index) { | ||
162 | if (((*it)->getTimeout().tv_sec > timer->getTimeout().tv_sec) || | ||
163 | (((*it)->getTimeout().tv_sec == timer->getTimeout().tv_sec) && | ||
164 | ((*it)->getTimeout().tv_usec >= timer->getTimeout().tv_usec))) { | ||
165 | break; | ||
166 | } | ||
167 | } | ||
168 | m_timerlist.insert(it, timer); | ||
169 | |||
170 | } | ||
79 | 171 | ||
80 | void BTimer::fireTimeout(void) { | 172 | void BTimer::removeTimer(BTimer *timer) { |
81 | if (handler) handler->timeout(); | 173 | assert(timer); |
174 | m_timerlist.remove(timer); | ||
82 | } | 175 | } |
176 | |||