split the OBTimerQueueManager and TimerQueue into their own files
[dana/openbox.git] / otk / timer.cc
1 // -*- mode: C++; indent-tabs-mode: nil; -*-
2
3 #ifdef    HAVE_CONFIG_H
4 #  include "../config.h"
5 #endif // HAVE_CONFIG_H
6
7 #include "timer.hh"
8 #include "timerqueuemanager.hh"
9
10 namespace otk {
11
12 static timeval normalizeTimeval(const timeval &tm)
13 {
14   timeval ret = tm;
15
16   while (ret.tv_usec < 0) {
17     if (ret.tv_sec > 0) {
18       --ret.tv_sec;
19       ret.tv_usec += 1000000;
20     } else {
21       ret.tv_usec = 0;
22     }
23   }
24
25   if (ret.tv_usec >= 1000000) {
26     ret.tv_sec += ret.tv_usec / 1000000;
27     ret.tv_usec %= 1000000;
28   }
29
30   if (ret.tv_sec < 0) ret.tv_sec = 0;
31
32   return ret;
33 }
34
35
36 OBTimer::OBTimer(OBTimerQueueManager *m, OBTimeoutHandler h, OBTimeoutData d)
37 {
38   manager = m;
39   handler = h;
40   data = d;
41
42   recur = timing = false;
43 }
44
45
46 OBTimer::~OBTimer(void)
47 {
48   if (timing) stop();
49 }
50
51
52 void OBTimer::setTimeout(long t)
53 {
54   _timeout.tv_sec = t / 1000;
55   _timeout.tv_usec = t % 1000;
56   _timeout.tv_usec *= 1000;
57 }
58
59
60 void OBTimer::setTimeout(const timeval &t)
61 {
62   _timeout.tv_sec = t.tv_sec;
63   _timeout.tv_usec = t.tv_usec;
64 }
65
66
67 void OBTimer::start(void)
68 {
69   gettimeofday(&_start, 0);
70
71   if (! timing) {
72     timing = true;
73     manager->addTimer(this);
74   }
75 }
76
77
78 void OBTimer::stop(void)
79 {
80   timing = false;
81
82   manager->removeTimer(this);
83 }
84
85
86 void OBTimer::halt(void)
87 {
88   timing = false;
89 }
90
91
92 void OBTimer::fireTimeout(void)
93 {
94   if (handler)
95     handler(data);
96 }
97
98
99 timeval OBTimer::timeRemaining(const timeval &tm) const
100 {
101   timeval ret = endpoint();
102
103   ret.tv_sec  -= tm.tv_sec;
104   ret.tv_usec -= tm.tv_usec;
105
106   return normalizeTimeval(ret);
107 }
108
109
110 timeval OBTimer::endpoint(void) const
111 {
112   timeval ret;
113
114   ret.tv_sec = _start.tv_sec + _timeout.tv_sec;
115   ret.tv_usec = _start.tv_usec + _timeout.tv_usec;
116
117   return normalizeTimeval(ret);
118 }
119
120
121 bool OBTimer::shouldFire(const timeval &tm) const
122 {
123   timeval end = endpoint();
124
125   return ! ((tm.tv_sec < end.tv_sec) ||
126             (tm.tv_sec == end.tv_sec && tm.tv_usec < end.tv_usec));
127 }
128
129 }