blob: 8f57916ff1a3df7050e24d7f42efa18099298e03 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#ifndef AOS_COMMON_TIME_H_
2#define AOS_COMMON_TIME_H_
3
4#include <stdint.h>
5#include <time.h>
brians57dd5822013-02-27 21:44:15 +00006#include <sys/time.h>
Brian4a424a22014-04-02 11:52:45 -07007#include <stdint.h>
8
9#include <type_traits>
Austin Schuh793d6b92016-05-01 13:28:14 -070010#include <chrono>
11#include <thread>
brians343bc112013-02-10 01:53:46 +000012#include <ostream>
13
brians343bc112013-02-10 01:53:46 +000014#include "aos/common/type_traits.h"
Brian Silvermanb407c672014-04-09 11:58:37 -070015#include "aos/common/macros.h"
brians343bc112013-02-10 01:53:46 +000016
17namespace aos {
Austin Schuh793d6b92016-05-01 13:28:14 -070018
19class monotonic_clock {
20 public:
21 typedef ::std::chrono::nanoseconds::rep rep;
22 typedef ::std::chrono::nanoseconds::period period;
23 typedef ::std::chrono::nanoseconds duration;
24 typedef ::std::chrono::time_point<monotonic_clock> time_point;
25
26 static monotonic_clock::time_point now() noexcept;
27 static constexpr bool is_steady = true;
28
29 // Returns the epoch (0).
30 static constexpr monotonic_clock::time_point epoch() {
Austin Schuh8aec1ed2016-05-01 13:29:20 -070031 return time_point(zero());
Austin Schuh793d6b92016-05-01 13:28:14 -070032 }
Austin Schuh8aec1ed2016-05-01 13:29:20 -070033
34 static constexpr monotonic_clock::duration zero() { return duration(0); }
Austin Schuh858c0212016-11-25 17:23:30 -080035
36 static constexpr time_point min_time{
37 time_point(duration(::std::numeric_limits<duration::rep>::min()))};
Austin Schuh793d6b92016-05-01 13:28:14 -070038};
39
brians343bc112013-02-10 01:53:46 +000040namespace time {
41
42// A nice structure for representing times.
43// 0 <= nsec_ < kNSecInSec should always be true. All functions here will make
44// sure that that is true if it was on all inputs (including *this).
45//
Brian Silverman6659bc32013-10-16 10:31:32 -070046// Negative times are supported so that all of the normal arithmetic identities
47// work. nsec_ is still always positive.
48//
brians343bc112013-02-10 01:53:46 +000049// The arithmetic and comparison operators are overloaded because they make
50// complete sense and are very useful. The default copy and assignment stuff is
Brian Silverman6659bc32013-10-16 10:31:32 -070051// left because it works fine. Multiplication of Times by Times is
brians343bc112013-02-10 01:53:46 +000052// not implemented because I can't think of any uses for them and there are
Brian Silverman6659bc32013-10-16 10:31:32 -070053// multiple ways to do it. Division of Times by Times is implemented as the
54// ratio of them. Multiplication, division, and modulus of Times by integers are
Brian Silverman0534df62014-05-26 21:19:15 -070055// implemented as interpreting the argument as nanoseconds. Modulus takes the
56// sign from the first operand.
brians343bc112013-02-10 01:53:46 +000057struct Time {
Brian Silverman52aeeac2013-08-28 16:20:53 -070058#ifdef SWIG
59// All of the uses of constexpr here can safely be simply removed.
60// NOTE: This means that relying on the fact that constexpr implicitly makes
Brian Silverman6659bc32013-10-16 10:31:32 -070061// member functions const is not valid, so they all have to be explicitly marked
62// const.
Brian Silverman52aeeac2013-08-28 16:20:53 -070063#define constexpr
64#endif // SWIG
brians343bc112013-02-10 01:53:46 +000065 public:
66 static const int32_t kNSecInSec = 1000000000;
67 static const int32_t kNSecInMSec = 1000000;
68 static const int32_t kNSecInUSec = 1000;
69 static const int32_t kMSecInSec = 1000;
70 static const int32_t kUSecInSec = 1000000;
Brian Silvermandcaa3f72015-11-29 05:32:08 +000071
72 static const Time kZero;
73
Brian Silverman92c3f1e2015-12-08 20:21:31 -050074 explicit constexpr Time(int32_t sec = 0, int32_t nsec = 0)
Brian Silverman52aeeac2013-08-28 16:20:53 -070075 : sec_(sec), nsec_(CheckConstexpr(nsec)) {
brians343bc112013-02-10 01:53:46 +000076 }
77 #ifndef SWIG
Brian Silverman52aeeac2013-08-28 16:20:53 -070078 explicit constexpr Time(const struct timespec &value)
79 : sec_(value.tv_sec), nsec_(CheckConstexpr(value.tv_nsec)) {
brians343bc112013-02-10 01:53:46 +000080 }
81 struct timespec ToTimespec() const {
82 struct timespec ans;
83 ans.tv_sec = sec_;
84 ans.tv_nsec = nsec_;
85 return ans;
86 }
Brian Silverman52aeeac2013-08-28 16:20:53 -070087 explicit constexpr Time(const struct timeval &value)
88 : sec_(value.tv_sec), nsec_(CheckConstexpr(value.tv_usec * kNSecInUSec)) {
brians57dd5822013-02-27 21:44:15 +000089 }
90 struct timeval ToTimeval() const {
91 struct timeval ans;
92 ans.tv_sec = sec_;
93 ans.tv_usec = nsec_ / kNSecInUSec;
94 return ans;
95 }
brians343bc112013-02-10 01:53:46 +000096 #endif // SWIG
Brian Silverman3204dd82013-03-12 18:42:01 -070097
Brian Silverman14fd0fb2014-01-14 21:42:01 -080098 // CLOCK_MONOTONIC on linux and CLOCK_REALTIME on the cRIO because the
brians343bc112013-02-10 01:53:46 +000099 // cRIO doesn't have any others.
100 // CLOCK_REALTIME is the default realtime clock and CLOCK_MONOTONIC doesn't
101 // change when somebody changes the wall clock (like the ntp deamon or
102 // whatever). See clock_gettime(2) for details.
103 //
104 // This is the clock that code that just wants to sleep for a certain amount
105 // of time or measure how long something takes should use.
106 #ifndef __VXWORKS__
107 static const clockid_t kDefaultClock = CLOCK_MONOTONIC;
108 #else
109 static const clockid_t kDefaultClock = CLOCK_REALTIME;
110 #endif
111 // Creates a Time representing the current value of the specified clock or
112 // dies.
113 static Time Now(clockid_t clock = kDefaultClock);
114
115 // Constructs a Time representing seconds.
Brian Silverman52aeeac2013-08-28 16:20:53 -0700116 static constexpr Time InSeconds(double seconds) {
117 return (seconds < 0.0) ?
118 Time(static_cast<int32_t>(seconds) - 1,
119 (seconds - static_cast<int32_t>(seconds) + 1.0) * kNSecInSec) :
120 Time(static_cast<int32_t>(seconds),
121 (seconds - static_cast<int32_t>(seconds)) * kNSecInSec);
brians343bc112013-02-10 01:53:46 +0000122 }
123
124 // Constructs a time representing microseconds.
Brian Silverman52aeeac2013-08-28 16:20:53 -0700125 static constexpr Time InNS(int64_t nseconds) {
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000126 return (nseconds < 0)
127 ? Time((nseconds - 1) / static_cast<int64_t>(kNSecInSec) - 1,
128 (((nseconds - 1) % kNSecInSec) + 1) + kNSecInSec)
129 : Time(nseconds / static_cast<int64_t>(kNSecInSec),
130 nseconds % kNSecInSec);
brians343bc112013-02-10 01:53:46 +0000131 }
132
133 // Constructs a time representing microseconds.
Brian Silverman52aeeac2013-08-28 16:20:53 -0700134 static constexpr Time InUS(int useconds) {
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000135 return (useconds < 0)
136 ? Time((useconds + 1) / kUSecInSec - 1,
137 (((useconds + 1) % kUSecInSec) - 1) * kNSecInUSec +
138 kNSecInSec)
139 : Time(useconds / kUSecInSec,
140 (useconds % kUSecInSec) * kNSecInUSec);
brians343bc112013-02-10 01:53:46 +0000141 }
142
143 // Constructs a time representing mseconds.
Brian Silverman52aeeac2013-08-28 16:20:53 -0700144 static constexpr Time InMS(int mseconds) {
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000145 return (mseconds < 0)
146 ? Time((mseconds + 1) / kMSecInSec - 1,
147 (((mseconds + 1) % kMSecInSec) - 1) * kNSecInMSec +
148 kNSecInSec)
149 : Time(mseconds / kMSecInSec,
150 (mseconds % kMSecInSec) * kNSecInMSec);
151 }
152
153 // Construct a time representing the period of hertz.
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700154 static constexpr ::std::chrono::nanoseconds FromRate(int hertz) {
155 return ::std::chrono::duration_cast<::std::chrono::nanoseconds>(
156 ::std::chrono::seconds(1)) /
157 hertz;
brians343bc112013-02-10 01:53:46 +0000158 }
159
160 // Checks whether or not this time is within amount nanoseconds of other.
161 bool IsWithin(const Time &other, int64_t amount) const;
162
163 // Returns the time represented all in nanoseconds.
Brian Silverman52aeeac2013-08-28 16:20:53 -0700164 int64_t constexpr ToNSec() const {
brians343bc112013-02-10 01:53:46 +0000165 return static_cast<int64_t>(sec_) * static_cast<int64_t>(kNSecInSec) +
166 static_cast<int64_t>(nsec_);
167 }
168#ifdef __VXWORKS__
169 // Returns the time represented all in system clock ticks. The system clock
170 // rate is retrieved using sysClkRateGet().
171 int ToTicks() const {
172 return ToNSec() / static_cast<int64_t>(kNSecInSec / sysClkRateGet());
173 }
Brian Silverman3204dd82013-03-12 18:42:01 -0700174 // Constructs a Time representing ticks.
175 static Time InTicks(int ticks) {
Brian Silvermanffe3d712013-03-15 21:35:59 -0700176 return Time::InSeconds(static_cast<double>(ticks) / sysClkRateGet());
Brian Silverman3204dd82013-03-12 18:42:01 -0700177 }
brians343bc112013-02-10 01:53:46 +0000178#endif
179
180 // Returns the time represented in milliseconds.
Brian Silverman52aeeac2013-08-28 16:20:53 -0700181 int64_t constexpr ToMSec() const {
brians343bc112013-02-10 01:53:46 +0000182 return static_cast<int64_t>(sec_) * static_cast<int64_t>(kMSecInSec) +
183 (static_cast<int64_t>(nsec_) / static_cast<int64_t>(kNSecInMSec));
184 }
185
Brian Silverman7645d2f2013-03-30 18:53:56 -0700186 // Returns the time represent in microseconds.
Brian Silverman52aeeac2013-08-28 16:20:53 -0700187 int64_t constexpr ToUSec() const {
Brian Silverman7645d2f2013-03-30 18:53:56 -0700188 return static_cast<int64_t>(sec_) * static_cast<int64_t>(kUSecInSec) +
189 (static_cast<int64_t>(nsec_) / static_cast<int64_t>(kNSecInUSec));
190 }
191
briansf0165ca2013-03-02 06:17:47 +0000192 // Returns the time represented in fractional seconds.
Brian Silverman52aeeac2013-08-28 16:20:53 -0700193 double constexpr ToSeconds() const {
briansf0165ca2013-03-02 06:17:47 +0000194 return static_cast<double>(sec_) + static_cast<double>(nsec_) / kNSecInSec;
195 }
196
brians343bc112013-02-10 01:53:46 +0000197 #ifndef SWIG
198 Time &operator+=(const Time &rhs);
199 Time &operator-=(const Time &rhs);
200 Time &operator*=(int32_t rhs);
201 Time &operator/=(int32_t rhs);
202 Time &operator%=(int32_t rhs);
Brian Silverman0079a9d2013-10-24 15:57:35 -0700203 Time &operator%=(double rhs) = delete;
204 Time &operator*=(double rhs) = delete;
205 Time &operator/=(double rhs) = delete;
206 const Time operator*(double rhs) const = delete;
207 const Time operator/(double rhs) const = delete;
208 const Time operator%(double rhs) const = delete;
brians343bc112013-02-10 01:53:46 +0000209 #endif
210 const Time operator+(const Time &rhs) const;
211 const Time operator-(const Time &rhs) const;
212 const Time operator*(int32_t rhs) const;
213 const Time operator/(int32_t rhs) const;
Brian Silverman2e0dcfd2013-03-30 22:44:40 -0700214 double operator/(const Time &rhs) const;
brians343bc112013-02-10 01:53:46 +0000215 const Time operator%(int32_t rhs) const;
216
Brian Silverman0079a9d2013-10-24 15:57:35 -0700217 const Time operator-() const;
218
brians343bc112013-02-10 01:53:46 +0000219 bool operator==(const Time &rhs) const;
220 bool operator!=(const Time &rhs) const;
221 bool operator<(const Time &rhs) const;
222 bool operator>(const Time &rhs) const;
223 bool operator<=(const Time &rhs) const;
224 bool operator>=(const Time &rhs) const;
225
226 #ifndef SWIG
227 // For gtest etc.
228 friend std::ostream &operator<<(std::ostream &os, const Time &time);
229 #endif // SWIG
230
Brian Silverman52aeeac2013-08-28 16:20:53 -0700231 int32_t constexpr sec() const { return sec_; }
brians343bc112013-02-10 01:53:46 +0000232 void set_sec(int32_t sec) { sec_ = sec; }
Brian Silverman52aeeac2013-08-28 16:20:53 -0700233 int32_t constexpr nsec() const { return nsec_; }
brians343bc112013-02-10 01:53:46 +0000234 void set_nsec(int32_t nsec) {
235 nsec_ = nsec;
236 Check();
237 }
238
Brian Silverman3204dd82013-03-12 18:42:01 -0700239 // Absolute value.
240 Time abs() const {
241 if (*this > Time(0, 0)) return *this;
Brian Silvermanf3cbebd2013-03-19 16:53:18 -0700242 if (nsec_ == 0) return Time(-sec_, 0);
Brian Silverman3204dd82013-03-12 18:42:01 -0700243 return Time(-sec_ - 1, kNSecInSec - nsec_);
244 }
245
246 // Enables returning the mock time value for Now instead of checking the
Brian Silverman6da04272014-05-18 18:47:48 -0700247 // system clock.
Brian Silvermanb407c672014-04-09 11:58:37 -0700248 static void EnableMockTime(const Time &now = Now());
249 // Calls SetMockTime with the current actual time.
250 static void UpdateMockTime();
Brian Silverman3204dd82013-03-12 18:42:01 -0700251 // Sets now when time is being mocked.
Brian Silverman6659bc32013-10-16 10:31:32 -0700252 static void SetMockTime(const Time &now);
253 // Convenience function to just increment the mock time by a certain amount in
254 // a thread safe way.
255 static void IncrementMockTime(const Time &amount);
Brian Silverman3204dd82013-03-12 18:42:01 -0700256 // Disables mocking time.
257 static void DisableMockTime();
258
brians343bc112013-02-10 01:53:46 +0000259 private:
260 int32_t sec_, nsec_;
Brian Silverman52aeeac2013-08-28 16:20:53 -0700261
262 // LOG(FATAL)s if nsec is >= kNSecInSec or negative.
263 static void CheckImpl(int32_t nsec);
264 void Check() { CheckImpl(nsec_); }
265 // A constexpr version of CheckImpl that returns the given value when it
Brian Silverman6659bc32013-10-16 10:31:32 -0700266 // succeeds or evaluates to non-constexpr and returns 0 when it fails.
267 // This will result in the usual LOG(FATAL) if this is used where it isn't
268 // required to be constexpr or a compile error if it is.
Brian Silverman52aeeac2013-08-28 16:20:53 -0700269 static constexpr int32_t CheckConstexpr(int32_t nsec) {
270 return (nsec >= kNSecInSec || nsec < 0) ? CheckImpl(nsec), 0 : nsec;
271 }
272
273#ifdef SWIG
274#undef constexpr
275#endif // SWIG
brians343bc112013-02-10 01:53:46 +0000276};
277
278// Sleeps for the amount of time represented by time counted by clock.
279void SleepFor(const Time &time, clockid_t clock = Time::kDefaultClock);
280// Sleeps until clock is at the time represented by time.
281void SleepUntil(const Time &time, clockid_t clock = Time::kDefaultClock);
282
Brian Silvermand0575692015-02-21 16:24:02 -0500283// Sets the global offset for all times so ::aos::time::Time::Now() will return
284// now.
285// There is no synchronization here, so this is only safe when only a single
286// task is running.
287// This is only allowed when the shared memory core infrastructure has been
288// initialized in this process.
289void OffsetToNow(const Time &now);
290
Brian Silvermanb407c672014-04-09 11:58:37 -0700291// RAII class that freezes Time::Now() (to avoid making large numbers of
292// syscalls to find the real time).
293class TimeFreezer {
294 public:
295 TimeFreezer() {
296 Time::EnableMockTime();
297 }
298 ~TimeFreezer() {
299 Time::DisableMockTime();
300 }
301
302 private:
303 DISALLOW_COPY_AND_ASSIGN(TimeFreezer);
304};
305
brians343bc112013-02-10 01:53:46 +0000306} // namespace time
307} // namespace aos
308
Austin Schuh793d6b92016-05-01 13:28:14 -0700309namespace std {
310namespace this_thread {
311// Template specialization for monotonic_clock, since we can use clock_nanosleep
312// with TIMER_ABSTIME and get very precise absolute time sleeps.
313template <>
314void sleep_until(const ::aos::monotonic_clock::time_point &end_time);
315
316} // namespace this_thread
317} // namespace std
318
319
brians343bc112013-02-10 01:53:46 +0000320#endif // AOS_COMMON_TIME_H_