]>
Dogcows Code - chaz/yoink/blob - src/moof/timer.cc
e31e49fdfb23a567ff857e46c4932e483d921fe3
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
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.
10 **************************************************************************/
25 scalar
timer::next_expiration_
= std::numeric_limits
<scalar
>::max();
26 hash
<unsigned,timer
*,hash_function
> timer::timers_
;
29 unsigned timer::new_identifier()
31 static unsigned id
= 1;
36 void timer::init(const function
& function
, scalar seconds
, mode mode
)
52 absolute_
= seconds
- ticks();
56 id_
= new_identifier();
57 timers_
.insert(std::pair
<unsigned,timer
*>(id_
, this));
59 if (absolute_
< next_expiration_
) next_expiration_
= absolute_
;
64 bool timer::is_valid() const
66 return mode_
!= invalid
;
69 void timer::invalidate()
76 if (is_equal(absolute_
, next_expiration_
))
78 next_expiration_
= find_next_expiration();
88 if (function_
) function_(*this, t
);
92 scalar absolute
= absolute_
;
94 if (is_equal(absolute_
, t
, 1.0)) absolute_
+= interval_
;
95 else absolute_
= interval_
+ t
;
97 if (is_equal(absolute
, next_expiration_
))
99 next_expiration_
= find_next_expiration();
109 scalar
timer::find_next_expiration()
111 scalar next_fire
= std::numeric_limits
<scalar
>::max();
113 hash
<unsigned,timer
*,hash_function
>::iterator it
;
114 for (it
= timers_
.begin(); it
!= timers_
.end(); ++it
)
116 scalar absolute
= (*it
).second
->absolute_
;
117 if (absolute
< next_fire
) next_fire
= absolute
;
124 scalar
timer::seconds_remaining() const
126 return absolute_
- ticks();
129 bool timer::is_expired() const
131 return seconds_remaining() < 0.0;
134 bool timer::is_repeating() const
136 return mode_
== repeat
;
140 void timer::fire_expired_timers()
142 fire_expired_timers(ticks());
145 void timer::fire_expired_timers(scalar t
)
147 if (next_expiration_
> t
) return;
149 hash
<unsigned,timer
*,hash_function
>::iterator it
;
150 for (it
= timers_
.begin(); it
!= timers_
.end(); ++it
)
152 timer
* timer
= (*it
).second
;
153 if (timer
->is_expired()) timer
->fire();
158 #if HAVE_CLOCK_GETTIME
160 // Since the monotonic clock will provide us with the time since the
161 // computer started, the number of seconds since that time could easily
162 // become so large that it cannot be accurately stored in a float (even
163 // with as little two days uptime), therefore we need to start from a more
164 // recent reference (when the program starts). Of course this isn't much
165 // of an issue if scalar is a double-precision number.
167 static time_t set_reference()
171 if (clock_gettime(CLOCK_MONOTONIC
, &ts
) != 0)
179 static const time_t reference_
= set_reference();
182 scalar
timer::ticks()
186 int result
= clock_gettime(CLOCK_MONOTONIC
, &ts
);
187 ASSERT(result
== 0 && "cannot access clock");
189 return scalar(ts
.tv_sec
- reference_
) +
190 scalar(ts
.tv_nsec
) / 1000000000.0;
193 void timer::sleep(scalar seconds
, mode mode
)
198 if (mode
== absolute
) seconds
-= ticks();
199 ts
.tv_sec
= time_t(seconds
);
200 ts
.tv_nsec
= long((seconds
- scalar(ts
.tv_sec
)) * 1000000000.0);
204 ret
= nanosleep(&ts
, &ts
);
206 while (ret
== -1 && errno
== EINTR
);
210 #else // ! HAVE_CLOCK_GETTIME
213 // If we don't have posix timers, we'll have to use a different timing
214 // method. SDL only promises centisecond accuracy, but that's better than
215 // a kick in the pants.
217 scalar
timer::ticks()
219 Uint32 ms
= SDL_GetTicks();
220 return scalar(ms
/ 1000) + scalar(ms
% 1000) / 1000.0;
223 void timer::sleep(scalar seconds
, mode mode
)
225 if (mode
== absolute
) seconds
-= ticks();
226 SDL_Delay(Uint32(clamp(int(seconds
* 1000.0), 0, 1000)));
229 #endif // HAVE_CLOCK_GETTIME
This page took 0.050804 seconds and 4 git commands to generate.