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