add the config header and emacs comment to all the .cc's
[mikachu/openbox.git] / 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 "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   if (_timing) {
81     _timing = false;
82
83     _manager->removeTimer(this);
84   }
85 }
86
87
88 void OBTimer::fire(void)
89 {
90   if (_handler)
91     _handler(_data);
92 }
93
94
95 timeval OBTimer::remainingTime(const timeval &tm) const
96 {
97   timeval ret = endTime();
98
99   ret.tv_sec  -= tm.tv_sec;
100   ret.tv_usec -= tm.tv_usec;
101
102   return normalizeTimeval(ret);
103 }
104
105
106 timeval OBTimer::endTime(void) const
107 {
108   timeval ret;
109
110   ret.tv_sec = _start.tv_sec + _timeout.tv_sec;
111   ret.tv_usec = _start.tv_usec + _timeout.tv_usec;
112
113   return normalizeTimeval(ret);
114 }
115
116
117 bool OBTimer::shouldFire(const timeval &tm) const
118 {
119   timeval end = endTime();
120
121   return ! ((tm.tv_sec < end.tv_sec) ||
122             (tm.tv_sec == end.tv_sec && tm.tv_usec < end.tv_usec));
123 }
124
125 }