]> Dogcows Code - chaz/openbox/blob - otk/timer.cc
no long used with our Timer-ng!
[chaz/openbox] / otk / timer.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif // HAVE_CONFIG_H
6
7 #include "timer.hh"
8 #include "display.hh"
9
10 namespace otk {
11
12 timeval Timer::_nearest_timeout, Timer::_now;
13 Timer::TimerQ Timer::_q;
14
15 void Timer::timevalAdd(timeval &a, long msec)
16 {
17 a.tv_sec += msec / 1000;
18 a.tv_usec += (msec % 1000) * 1000;
19 a.tv_sec += a.tv_usec / 1000000;
20 a.tv_usec %= 1000000;
21 }
22
23 bool Timer::nearestTimeout(struct timeval &tm)
24 {
25 if (_q.empty())
26 return false;
27 tm.tv_sec = _nearest_timeout.tv_sec - _now.tv_sec;
28 tm.tv_usec = _nearest_timeout.tv_usec - _now.tv_usec;
29
30 while (tm.tv_usec < 0) {
31 tm.tv_usec += 1000000;
32 tm.tv_sec--;
33 }
34 tm.tv_sec += tm.tv_usec / 1000000;
35 tm.tv_usec %= 1000000;
36 if (tm.tv_sec < 0)
37 tm.tv_sec = 0;
38
39 return true;
40 }
41
42 void Timer::dispatchTimers(bool wait)
43 {
44 fd_set selset;
45 int fd;
46 timeval next;
47 Timer *curr;
48
49 gettimeofday(&_now, NULL);
50 _nearest_timeout = _now;
51 _nearest_timeout.tv_sec += 10000;
52
53 while (!_q.empty()) {
54 curr = _q.top();
55 /* since we overload the destructor to keep from removing from the middle of
56 the priority queue, set _del_me, we have to do our real delete in here.
57 */
58 if (curr->_del_me) {
59 _q.pop();
60 realDelete(curr);
61 continue;
62 }
63
64 // the queue is sorted, so if this timer shouldn't fire, none are ready
65 _nearest_timeout = curr->_timeout;
66 if (!timercmp(&_now, &_nearest_timeout, >))
67 break;
68
69 /* we set the last fired time to delay msec after the previous firing, then
70 re-insert. timers maintain their order and may trigger more than once if
71 they've waited more than one delay's worth of time.
72 */
73 _q.pop();
74 timevalAdd(curr->_last, curr->_delay);
75 curr->_action(curr->_data);
76 timevalAdd(curr->_timeout, curr->_delay);
77 _q.push(curr);
78 }
79
80 if (wait) {
81 // wait for the nearest trigger, or for X to do something interesting
82 fd = ConnectionNumber(**display);
83 FD_ZERO(&selset);
84 FD_SET(fd, &selset);
85 if (nearestTimeout(next))
86 select(fd + 1, &selset, NULL, NULL, &next);
87 else
88 select(fd + 1, &selset, NULL, NULL, NULL);
89 }
90 }
91
92 Timer::Timer(long delay, Timer::TimeoutHandler action, void *data)
93 : _delay(delay),
94 _action(action),
95 _data(data),
96 _del_me(false),
97 _last(_now),
98 _timeout(_now)
99 {
100 timevalAdd(_timeout, delay);
101 _q.push(this);
102 }
103
104 void Timer::operator delete(void *self)
105 {
106 Timer *t;
107 t = (Timer *)self;
108 t->_del_me = true;
109 }
110
111 void Timer::realDelete(Timer *me)
112 {
113 ::delete me;
114 }
115
116 void Timer::initialize(void)
117 {
118 gettimeofday(&_now, NULL);
119 _nearest_timeout.tv_sec = 100000;
120 _nearest_timeout.tv_usec = 0;
121 }
122
123 void Timer::destroy(void)
124 {
125 while(!_q.empty()) {
126 realDelete(_q.top());
127 _q.pop();
128 }
129 }
130
131 }
This page took 0.037095 seconds and 4 git commands to generate.