testing improved runloop scheduling
[chaz/yoink] / src / moof / timer.hh
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
11
12 #ifndef _MOOF_TIMER_HH_
13 #define _MOOF_TIMER_HH_
14
15 /**
16 * \file timer.hh
17 * Functions for measuring time in a friendly unit.
18 */
19
20 #include <boost/bind.hpp>
21 #include <boost/function.hpp>
22 #include <boost/noncopyable.hpp>
23
24 #include <moof/hash.hh>
25 #include <moof/math.hh>
26
27
28 namespace moof {
29
30
31 /**
32 * A class to represent a timer for scheduled events. The timer events
33 * will be executed on or sometime after their schedculed time. The
34 * runloop associated with the current running view will make an attempt to
35 * fire any expired timers as close to their scheduled times as possible.
36 */
37 class timer : public boost::noncopyable
38 {
39 public:
40
41 /**
42 * A type for the state of a timer.
43 */
44 enum mode
45 {
46 invalid = -1, /// Timer is not scheduled.
47 relative = 0, /// Timer is scheduled by a relative time.
48 absolute = 1, /// Timer is scheduled by an absolute time.
49 repeat = 2 /// Timer is scheduled by a periodic time.
50 };
51
52 /**
53 * Function protocol for a timer event handler. A function matching
54 * this protocol will be called when the timer expires. The function
55 * takes two parameters: the timer object that just expired, and the
56 * absolute time.
57 */
58 typedef boost::function<void(timer&,scalar)> function;
59
60
61 /**
62 * Construct an invalid (uninitialized) timer.
63 */
64 timer() :
65 mode_(invalid),
66 absolute_(SCALAR(0.0)) {}
67
68 /**
69 * Construct a scheduled timer.
70 * \param function The event handler.
71 * \param seconds The number of seconds; the meaning of this depends on
72 * the mode of the timer.
73 * \param mode The timer mode. If the mode is relative (default), the
74 * seconds parameter is the number of seconds from the current time to
75 * wait before expiring the timer. If the mode is absolute, the
76 * seconds parameter is the number of seconds from some arbitrary,
77 * fixed time in the past. If the mode is repeat, the seconds
78 * parameter is the number of seconds from now to wait before expiring
79 * the timer, at which time the timer will be rescheduled to expired
80 * again at that many seconds from the expiration time. A repeating
81 * timer can be invalidated manually using invalidate().
82 */
83 timer(const function& function, scalar seconds, mode mode = relative)
84 {
85 init(function, seconds, mode);
86 }
87
88 /**
89 * Deconstruct a timer. This will automagically invalidate the timer,
90 * so it will not expire or fire an event.
91 */
92 ~timer()
93 {
94 invalidate();
95 }
96
97
98 /**
99 * Initialize a timer with a scheduled time. If the timer is already
100 * scheduled, its prior schedule will be invalidated and replaced by
101 * this new schedule.
102 * \param function The event handler.
103 * \param seconds The number of seconds; the meaning of this depends on
104 * the mode of the timer.
105 * \param mode The timer mode. If the mode is relative (default), the
106 * seconds parameter is the number of seconds from the current time to
107 * wait before expiring the timer. If the mode is absolute, the
108 * seconds parameter is the number of seconds from some arbitrary,
109 * fixed time in the past. If the mode is repeat, the seconds
110 * parameter is the number of seconds from now to wait before expiring
111 * the timer, at which time the timer will be rescheduled to expired
112 * again at that many seconds from the expiration time. A repeating
113 * timer can be invalidated manually using invalidate().
114 */
115 void init(const function& function,
116 scalar seconds,
117 mode mode = relative);
118
119
120 /**
121 * Get whether or not the timer is valid. If a timer is valid, it is
122 * still scheduled to expired. You can get the time remaining from
123 * seconds_remaining().
124 */
125 bool is_valid() const;
126
127 /**
128 * Manually invalidated the timer, removing any schedule such that the
129 * timer will not expired and no event will be fired.
130 */
131 void invalidate();
132
133
134 /**
135 * Manually fire the timer event. Usually, the timer event will be
136 * fired when the timer expires, but this can be used to fire it
137 * prematurely. If the timer is scheduled, it will be invalidated. If
138 * the timer is already invalid (but is initialized with an event
139 * handler), the event will be fired and the timer will remain invalid.
140 */
141 void fire();
142
143
144 /**
145 * Get the number of seconds remaining before the timer is scheduled to
146 * expired. If the timer is invalid, the retured value will be
147 * negative.
148 * \return Seconds.
149 */
150 scalar seconds_remaining() const;
151
152 scalar next_expiration() const;
153
154 /**
155 * Get whether or not the timer is expired. A timer on a repeating
156 * schedule will never be expired since it will always have a scheduled
157 * expiration time in the future. If the timer is expired but not
158 * invalid, the timer event has not yet fired; the timer will be
159 * invalidated when it does fire.
160 * \return True if the timer is expired, false otherwise.
161 */
162 bool is_expired() const;
163
164 /**
165 * Get whether or not the timer is on a repeating schedule.
166 * \return True if the timer is repeating, false otherwise.
167 */
168 bool is_repeating() const;
169
170
171 /**
172 * Get the number of seconds since a fixed, arbitrary point in the
173 * past.
174 * \return Seconds.
175 */
176 static scalar ticks();
177
178
179 /**
180 * Put the thread to sleep for a certain period of time. If absolute
181 * is true, then it will sleep until seconds after the fixed time in
182 * the past. If absolute is false, it will sleep for seconds starting
183 * now. Unlike system sleep functions, this one automatically resumes
184 * sleep if sleep was interrupted by a signal. Therefore, calling this
185 * function is guaranteed to sleep for the requested amount of time
186 * (and maybe longer).
187 * \param seconds Number of seconds.
188 * \param mode The timer mode.
189 */
190 static void sleep(scalar seconds, mode mode = relative);
191
192
193 /**
194 * Get the absolute time when the next timer is scheduled to expire.
195 * \return Absolute time, in seconds.
196 */
197 static scalar next_event()
198 {
199 return next_event_;
200 }
201
202
203 /**
204 * Fire any timers which are not yet invalidated but have an expiration
205 * time in the past.
206 */
207 static void fire_expired_timers()
208 {
209 fire_expired_timers(ticks());
210 }
211
212 /**
213 * Fire any timers which are not yet invalidated but have an expiration
214 * time before a given absolute time.
215 */
216 static void fire_expired_timers(scalar t);
217
218
219 private:
220
221 static unsigned new_identifier();
222 static scalar find_next_event();
223
224 function function_;
225 mode mode_;
226 scalar absolute_;
227 scalar interval_;
228 unsigned id_;
229
230 static scalar next_event_;
231 static hash<unsigned,timer*,hash_function> timers_;
232 };
233
234
235 } // namespace moof
236
237 #endif // _MOOF_TIMER_HH_
238
This page took 0.040445 seconds and 4 git commands to generate.