]> Dogcows Code - chaz/yoink/blob - src/moof/timer.cc
further implementing runloop support
[chaz/yoink] / src / moof / timer.cc
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 #include "config.h"
13
14 #include <cerrno>
15 #include <ctime>
16 #include <limits>
17
18 #include <SDL/SDL.h>
19
20 #include "debug.hh"
21 #include "runloop.hh"
22 #include "timer.hh"
23
24
25 namespace moof {
26
27
28 void timer::init(const function& function,
29 scalar seconds,
30 enum mode mode,
31 timer_source& source)
32 {
33 source_ = &source;
34
35 invalidate();
36 if ((mode_ = mode) != invalid)
37 {
38 function_ = function;
39
40 if (mode == absolute)
41 {
42 absolute_ = seconds;
43 }
44 else
45 {
46 absolute_ = seconds + source_->ticks();
47 interval_ = seconds;
48 }
49 }
50 }
51
52 timer::~timer()
53 {
54 detach_from_runloop();
55 }
56
57 void timer::invalidate()
58 {
59 mode_ = invalid;
60 absolute_ = SCALAR(0.0);
61 }
62
63
64 void timer::added_to_runloop(runloop& runloop)
65 {
66 detach_from_runloop();
67 runloop_ = &runloop;
68 }
69
70 void timer::detach_from_runloop()
71 {
72 if (runloop_)
73 {
74 runloop_->remove_timer(*this);
75 runloop_ = 0;
76 }
77 }
78
79
80 void timer::fire(scalar t)
81 {
82 if (function_) function_(*this, t);
83
84 if (mode_ == repeat)
85 {
86 if (is_equal(absolute_, t, 1.0)) absolute_ += interval_;
87 else absolute_ = interval_ + t;
88 }
89 else invalidate();
90 }
91
92
93 scalar timer::ticks()
94 {
95 return default_source().ticks();
96 }
97
98
99
100 #if ENABLE_CLOCK_GETTIME
101
102 class real_time : public timer_source
103 {
104 public:
105
106 real_time() :
107 scale_(SCALAR(1.0))
108 {
109 reset();
110 }
111
112
113 scalar ticks() const
114 {
115 struct timespec ts;
116 int result = clock_gettime(CLOCK_MONOTONIC, &ts);
117 ASSERT(result == 0 && "monotonic clock not available");
118
119 return reference_ +
120 (scalar(ts.tv_sec - start_.tv_sec) +
121 scalar(ts.tv_nsec - start_.tv_nsec) *
122 SCALAR(0.000000001)) * scale_;
123 }
124
125 void reset()
126 {
127 reference_ = SCALAR(0.0);
128 clock_gettime(CLOCK_MONOTONIC, &start_);
129 }
130
131 void scale(scalar factor)
132 {
133 reference_ = ticks();
134 clock_gettime(CLOCK_MONOTONIC, &start_);
135 scale_ = factor;
136 }
137
138
139 private:
140
141 scalar reference_;
142 struct timespec start_;
143 scalar scale_;
144 };
145
146
147 void timer::sleep(scalar seconds, enum mode mode)
148 {
149 if (mode == absolute) seconds -= ticks();
150 if (seconds < SCALAR(0.0)) return;
151
152 struct timespec ts;
153 ts.tv_sec = seconds;
154 ts.tv_nsec = (seconds - scalar(ts.tv_sec)) * SCALAR(1000000000.0);
155
156 int ret;
157 do ret = nanosleep(&ts, &ts); while (ret == -1 && errno == EINTR);
158 }
159
160
161 #else // ! ENABLE_CLOCK_GETTIME
162
163
164 class real_time : public timer_source
165 {
166 public:
167
168 real_time() :
169 scale_(SCALAR(1.0))
170 {
171 reset();
172 }
173
174
175 scalar ticks() const
176 {
177 return reference_ + scalar(SDL_GetTicks() - start_) * scale_;
178 }
179
180 void reset()
181 {
182 reference_ = SCALAR(0.0);
183 start_ = SDL_GetTicks();
184 }
185
186 void scale(scalar factor)
187 {
188 reference_ = ticks();
189 start_ = SDL_GetTicks();
190 scale_ = factor * SCALAR(0.001);
191 }
192
193
194 private:
195
196 scalar reference_;
197 Uint32 start_;
198 scalar scale_;
199 };
200
201
202 void timer::sleep(scalar seconds, mode mode)
203 {
204 if (mode == absolute) seconds -= ticks();
205 if (seconds < SCALAR(0.0)) return;
206 SDL_Delay(seconds * SCALAR(1000.0));
207 }
208
209 #endif // ENABLE_CLOCK_GETTIME
210
211
212 timer_source& timer::default_source()
213 {
214 static real_time t;
215 return t;
216 }
217
218
219 } // namespace moof
220
This page took 0.038439 seconds and 4 git commands to generate.