Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
TimeBase.hxx
Go to the documentation of this file.
1
35#ifndef _UTILS_TIMEBASE_HXX_
36#define _UTILS_TIMEBASE_HXX_
37
38#include <time.h>
39#include "os/OS.hxx"
40
43class TimeBase : protected Atomic
44{
45public:
46 TimeBase()
47 : started_(false)
48 { }
49
53 void sync(const TimeBase &other)
54 {
55 timestamp_ = other.timestamp_;
56 seconds_ = other.seconds_;
57 rate_ = other.rate_;
58 started_ = other.started_;
59 }
60
64 std::pair<time_t, int16_t> time_and_rate_quarters()
65 {
66 AtomicHolder h(this);
67 return std::make_pair(time(), rate_);
68 }
69
74 time_t compare_realtime(time_t t1, time_t t2)
75 {
76 int rate = rate_;
77 if (rate == 0)
78 {
79 // avoid divid by zero error
80 rate = 4;
81 }
82 return ((t1 - t2) * 4) / rate;
83 }
84
87 time_t time()
88 {
89 AtomicHolder h(this);
90 if (started_)
91 {
92 long long elapsed = OSTime::get_monotonic() - timestamp_;
93 elapsed = ((elapsed * std::abs(rate_)) + 2) / 4;
94
95 time_t diff = (time_t)NSEC_TO_SEC_ROUNDED(elapsed);
96 return (rate_ < 0) ? seconds_ - diff : seconds_ + diff;
97 }
98 else
99 {
100 // clock is stopped, time is not progressing
101 return seconds_;
102 }
103 }
104
108 struct tm *gmtime_r(struct tm *result)
109 {
110 time_t now = time();
111 return ::gmtime_r(&now, result);
112 }
113
118 int date(int *month, int *day)
119 {
120 struct tm tm;
121 if (gmtime_r(&tm) == nullptr)
122 {
123 return -1;
124 }
125 *month = tm.tm_mon + 1;
126 *day = tm.tm_mday;
127 return 0;
128 }
129
134 {
135 struct tm tm;
136 if (gmtime_r(&tm) == nullptr)
137 {
138 return -1;
139 }
140 return tm.tm_wday;
141 }
142
146 {
147 struct tm tm;
148 if (gmtime_r(&tm) == nullptr)
149 {
150 return -1;
151 }
152 return tm.tm_yday;
153 }
154
157 int year()
158 {
159 struct tm tm;
160 if (gmtime_r(&tm) == nullptr)
161 {
162 return -1;
163 }
164 return tm.tm_year + 1900;
165 }
166
171 {
172 return rate_;
173 }
174
179 {
180 AtomicHolder h(this);
181 return rate_ != 0 && started_;
182 }
183
187 {
188 return started_;
189 }
190
198 int16_t rate, time_t fast_sec, long long *real_nsec)
199 {
200 if (rate != 0 && rate >= -2048 && rate <= 2047)
201 {
202 *real_nsec =
203 ((SEC_TO_NSEC(std::abs(fast_sec)) * 4) + (std::abs(rate) / 2)) /
204 rate;
205 if (fast_sec < 0)
206 {
207 *real_nsec = -(*real_nsec);
208 }
209 return true;
210 }
211 else
212 {
213 return false;
214 }
215 }
216
224 int16_t rate, long long real_nsec, time_t *fast_sec)
225 {
226 if (rate != 0 && rate >= -2048 && rate <= 2047)
227 {
228 *fast_sec = (std::abs(NSEC_TO_SEC(real_nsec * rate)) + 2) / 4;
229 if ((real_nsec < 0 && rate > 0) || (real_nsec >= 0 && rate < 0))
230 {
231 *fast_sec = -(*fast_sec);
232 }
233 return true;
234 }
235 else
236 {
237 return false;
238 }
239 }
240
249 bool real_nsec_until_fast_time_abs(time_t fast_sec, long long *real_nsec)
250 {
251 if (fast_sec_to_real_nsec_period_abs(fast_sec - seconds_, real_nsec))
252 {
253 *real_nsec += timestamp_;
254 long long monotonic = OSTime::get_monotonic();
255 *real_nsec -= monotonic;
256 return true;
257 }
258 else
259 {
260 return false;
261 }
262 }
263
273 bool fast_sec_to_real_nsec_period_abs(time_t fast_sec, long long *real_nsec)
274 {
275 if (fast_sec_to_real_nsec_period(rate_, fast_sec, real_nsec))
276 {
277 *real_nsec = std::abs(*real_nsec);
278 return true;
279 }
280 else
281 {
282 return false;
283 }
284 }
285
286protected:
290 time_t seconds_ {0};
291 int16_t rate_ {0};
292
293 uint16_t started_ : 1;
294};
295
296#endif // _UTILS_TIMEBASE_HXX_
See OSMutexLock in os/OS.hxx.
Definition Atomic.hxx:153
Lightweight locking class for protecting small critical sections.
Definition Atomic.hxx:130
static long long get_monotonic()
Get the monotonic time since the system started.
Definition OS.hxx:560
Helper class for implementing fast clocks.
Definition TimeBase.hxx:44
int day_of_week()
Get the day of the week.
Definition TimeBase.hxx:133
bool real_nsec_to_fast_sec_period(int16_t rate, long long real_nsec, time_t *fast_sec)
Convert period in real nsec to a fast clock period.
Definition TimeBase.hxx:223
bool fast_sec_to_real_nsec_period_abs(time_t fast_sec, long long *real_nsec)
Convert fast clock absolute (negative or positive) period to a positive (absolute) period in real nse...
Definition TimeBase.hxx:273
struct tm * gmtime_r(struct tm *result)
Get the time as a standard struct tm.
Definition TimeBase.hxx:108
uint16_t started_
true if clock is started
Definition TimeBase.hxx:293
time_t seconds_
Clock time at the last time update.
Definition TimeBase.hxx:290
int day_of_year()
Get the day of the year.
Definition TimeBase.hxx:145
int date(int *month, int *day)
Get the date (month/day).
Definition TimeBase.hxx:118
bool is_started()
Test of the clock is started (rate could still be 0).
Definition TimeBase.hxx:186
std::pair< time_t, int16_t > time_and_rate_quarters()
Get the time as a value of seconds relative to the system epoch.
Definition TimeBase.hxx:64
int16_t get_rate_quarters()
Report the clock rate as a 12-bit fixed point number (-512.00 to 511.75).
Definition TimeBase.hxx:170
int year()
Get the year.
Definition TimeBase.hxx:157
bool is_running()
Test of the clock is running.
Definition TimeBase.hxx:178
long long timestamp_
OS time at the last time update.
Definition TimeBase.hxx:288
bool real_nsec_until_fast_time_abs(time_t fast_sec, long long *real_nsec)
Convert a fast time to absolute nsec until it will occur.
Definition TimeBase.hxx:249
time_t compare_realtime(time_t t1, time_t t2)
Get the difference in time scaled to real time.
Definition TimeBase.hxx:74
time_t time()
Get the time as a value of seconds relative to the system epoch.
Definition TimeBase.hxx:87
void sync(const TimeBase &other)
Synchronizes this time with a different clock.
Definition TimeBase.hxx:53
bool fast_sec_to_real_nsec_period(int16_t rate, time_t fast_sec, long long *real_nsec)
Convert fast clock period to a period in real nsec.
Definition TimeBase.hxx:197
int16_t rate_
effective clock rate
Definition TimeBase.hxx:291
#define NSEC_TO_SEC_ROUNDED(_nsec)
Convert a nanosecond value to a second value.
Definition os.h:318
#define SEC_TO_NSEC(_sec)
Convert a second value to a nanosecond value.
Definition os.h:286
#define NSEC_TO_SEC(_nsec)
Convert a nanosecond value to a second value.
Definition os.h:238