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