1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Timer.hh for Blackbox - An X11 Window Manager
3 // Copyright (c) 2001 - 2005 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000, 2002 - 2005
5 //         Bradley T Hughes <bhughes at trolltech.com>
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a
8 // copy of this software and associated documentation files (the "Software"),
9 // to deal in the Software without restriction, including without limitation
10 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 // and/or sell copies of the Software, and to permit persons to whom the
12 // Software is furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 // DEALINGS IN THE SOFTWARE.
24 
25 #ifndef   __Timer_hh
26 #define   __Timer_hh
27 
28 #include "Util.hh"
29 
30 #include <algorithm>
31 #include <queue>
32 #include <vector>
33 
34 // forward declare to avoid the header
35 struct timeval;
36 
37 namespace bt {
38 
39   // use a wrapper class to avoid the header as well
40   struct timeval {
41     long tv_sec;
42     long tv_usec;
43 
timevalbt::timeval44     inline timeval(void)
45       : tv_sec(0l), tv_usec(0l)
46     { }
timevalbt::timeval47     inline timeval(long s, long u)
48       : tv_sec(s), tv_usec(u)
49     { }
50 
51     bool operator<(const timeval &);
52     timeval operator+(const timeval &);
53     timeval &operator+=(const timeval &tv);
54     timeval operator-(const timeval &);
55     timeval &operator-=(const timeval &tv);
56 
57     // POSIX<->bt conversion
58     timeval(const ::timeval &);
59     timeval &operator=(const ::timeval &);
60     operator ::timeval() const;
61   };
62 
63   timeval normalizeTimeval(const timeval &tm);
64 
65   // forward declaration
66   class TimerQueueManager;
67   class Timer;
68 
69   class TimeoutHandler {
70   public:
71     virtual void timeout(Timer *t) = 0;
72   };
73 
74   class Timer: public NoCopy {
75   private:
76     TimerQueueManager *manager;
77     TimeoutHandler *handler;
78     bool timing, recur;
79 
80     timeval _start, _timeout;
81 
82   public:
83     Timer(TimerQueueManager *m, TimeoutHandler *h);
84     virtual ~Timer(void);
85 
86     void fireTimeout(void);
87 
isTiming(void) const88     inline bool isTiming(void) const
89     { return timing; }
isRecurring(void) const90     inline bool isRecurring(void) const
91     { return recur; }
92 
timeout(void) const93     inline const timeval &timeout(void) const
94     { return _timeout; }
startTime(void) const95     inline const timeval &startTime(void) const
96     { return _start; }
97 
98     // adjust the start time by the given offset... this is done when
99     // the clock rolls back
100     void adjustStartTime(const timeval &offset);
101 
102     timeval timeRemaining(const timeval &tm) const;
103     bool shouldFire(const timeval &tm) const;
104     timeval endpoint(void) const;
105 
recurring(bool b)106     inline void recurring(bool b)
107     { recur = b; }
108 
109     void setTimeout(long t);
110     void setTimeout(const timeval &t);
111 
112     void start(void);  // manager acquires timer
113     void stop(void);   // manager releases timer
114     void halt(void);   // halts the timer
115 
operator <(const Timer & other) const116     inline bool operator<(const Timer& other) const
117     { return shouldFire(other.endpoint()); }
118   };
119 
120   template <class _Tp, class _Sequence, class _Compare>
121   class _timer_queue: protected std::priority_queue<_Tp, _Sequence, _Compare> {
122   public:
123     typedef std::priority_queue<_Tp, _Sequence, _Compare> _Base;
124 
_timer_queue(void)125     inline _timer_queue(void)
126       : _Base()
127     { }
~_timer_queue(void)128     inline ~_timer_queue(void)
129     { }
130 
release(const _Tp & value)131     inline void release(const _Tp& value) {
132       _Base::c.erase(std::remove(_Base::c.begin(), _Base::c.end(), value),
133                      _Base::c.end());
134       // after removing the item we need to make the heap again
135       std::make_heap(_Base::c.begin(), _Base::c.end(), _Base::comp);
136     }
empty(void) const137     inline bool empty(void) const
138     { return _Base::empty(); }
size(void) const139     inline size_t size(void) const
140     { return _Base::size(); }
push(const _Tp & value)141     inline void push(const _Tp& value)
142     { _Base::push(value); }
pop(void)143     inline void pop(void)
144     { _Base::pop(); }
top(void) const145     inline const _Tp& top(void) const
146     { return _Base::top(); }
147   private:
148     // no copying!
149     _timer_queue(const _timer_queue&);
150     _timer_queue& operator=(const _timer_queue&);
151   };
152 
153   struct TimerLessThan {
operator ()bt::TimerLessThan154     inline bool operator()(const Timer* const l, const Timer* const r) const
155     { return *r < *l; }
156   };
157 
158   typedef _timer_queue<Timer*, std::vector<Timer*>, TimerLessThan> TimerQueue;
159 
160   class TimerQueueManager {
161   public:
162     virtual void addTimer(Timer* timer) = 0;
163     virtual void removeTimer(Timer* timer) = 0;
164   };
165 
166 } // namespace bt
167 
168 #endif // __Timer_hh
169