]> Dogcows Code - chaz/yoink/blob - src/moof/timer.cc
fixed documentation about where to find licenses
[chaz/yoink] / src / moof / timer.cc
1
2 /*] Copyright (c) 2009-2011, Charles McGarvey [*****************************
3 **] All rights reserved.
4 *
5 * Distributable under the terms and conditions of the 2-clause BSD license;
6 * see the file COPYING for a complete text of the license.
7 *
8 *****************************************************************************/
9
10 #if HAVE_CONFIG_H
11 #include "config.h"
12 #endif
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, enum mode mode, timer_source& source)
30 {
31 source_ = &source;
32
33 invalidate();
34 if ((mode_ = mode) != invalid)
35 {
36 function_ = function;
37
38 if (mode == absolute)
39 {
40 absolute_ = seconds;
41 }
42 else
43 {
44 absolute_ = seconds + source_->ticks();
45 interval_ = seconds;
46 }
47 }
48 }
49
50 timer::~timer()
51 {
52 detach_from_runloop();
53 }
54
55 void timer::invalidate()
56 {
57 mode_ = invalid;
58 absolute_ = SCALAR(0.0);
59 }
60
61 void timer::added_to_runloop(runloop& runloop)
62 {
63 detach_from_runloop();
64 runloop_ = &runloop;
65 }
66
67 void timer::detach_from_runloop()
68 {
69 if (runloop_)
70 {
71 runloop_->remove_timer(*this);
72 runloop_ = 0;
73 }
74 }
75
76 void timer::fire(scalar t)
77 {
78 if (function_) function_(*this, t);
79
80 if (mode_ == repeat)
81 {
82 if (is_equal(absolute_, t, 1.0))
83 absolute_ += interval_;
84 else
85 absolute_ = interval_ + t;
86 // TODO error accumulates in absolute var
87 }
88 else
89 {
90 invalidate();
91 }
92 }
93
94 scalar timer::ticks()
95 {
96 return default_source().ticks();
97 }
98
99 #if ENABLE_CLOCK_GETTIME
100 class real_time : public timer_source
101 {
102 public:
103
104 real_time() :
105 scale_(SCALAR(1.0))
106 {
107 reset();
108 }
109
110 scalar ticks() const
111 {
112 struct timespec ts;
113 int result = clock_gettime(CLOCK_MONOTONIC, &ts);
114 ASSERT(result == 0 && "monotonic clock not available");
115
116 return reference_ +
117 (scalar(ts.tv_sec - start_.tv_sec) +
118 scalar(ts.tv_nsec - start_.tv_nsec) *
119 SCALAR(0.000000001)) * scale_;
120 }
121
122 void reset()
123 {
124 reference_ = SCALAR(0.0);
125 clock_gettime(CLOCK_MONOTONIC, &start_);
126 }
127
128 void scale(scalar factor)
129 {
130 reference_ = ticks();
131 clock_gettime(CLOCK_MONOTONIC, &start_);
132 scale_ = factor;
133 }
134
135 private:
136
137 scalar reference_;
138 struct timespec start_;
139 scalar scale_;
140 };
141
142 void timer::sleep(scalar seconds, enum mode mode)
143 {
144 if (mode == absolute) seconds -= ticks();
145 if (seconds < SCALAR(0.0)) return;
146
147 struct timespec ts;
148 ts.tv_sec = seconds;
149 ts.tv_nsec = (seconds - scalar(ts.tv_sec)) * SCALAR(1000000000.0);
150
151 int ret;
152 do ret = nanosleep(&ts, &ts);
153 while (ret == -1 && errno == EINTR);
154 }
155
156 #else // ! ENABLE_CLOCK_GETTIME
157 class real_time : public timer_source
158 {
159 public:
160
161 real_time() :
162 scale_(SCALAR(0.001))
163 {
164 reset();
165 }
166
167 scalar ticks() const
168 {
169 return reference_ + scalar(SDL_GetTicks() - start_) * scale_;
170 }
171
172 void reset()
173 {
174 reference_ = SCALAR(0.0);
175 start_ = SDL_GetTicks();
176 }
177
178 void scale(scalar factor)
179 {
180 reference_ = ticks();
181 start_ = SDL_GetTicks();
182 scale_ = factor * SCALAR(0.001);
183 }
184
185 private:
186
187 scalar reference_;
188 Uint32 start_;
189 scalar scale_;
190 };
191
192 void timer::sleep(scalar seconds, enum mode mode)
193 {
194 if (mode == absolute) seconds -= ticks();
195 if (seconds < SCALAR(0.0)) return;
196 SDL_Delay(seconds * SCALAR(1000.0));
197 }
198 #endif // ENABLE_CLOCK_GETTIME
199
200 timer_source& timer::default_source()
201 {
202 static real_time t;
203 return t;
204 }
205
206
207 } // namespace moof
208
This page took 0.037909 seconds and 4 git commands to generate.