blob: 418d0872da35c3c6a42fd31971b2a2bde4cfec49 [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>
6
7#ifndef __VXWORKS__
8#include <type_traits>
brians57dd5822013-02-27 21:44:15 +00009#include <sys/time.h>
brians343bc112013-02-10 01:53:46 +000010#else
11#include <sysLib.h>
brians57dd5822013-02-27 21:44:15 +000012#include <sys/times.h>
brians343bc112013-02-10 01:53:46 +000013#endif
14#include <ostream>
15
16#include "aos/aos_stdint.h"
17#include "aos/common/type_traits.h"
18
19namespace aos {
20namespace time {
21
22// A nice structure for representing times.
23// 0 <= nsec_ < kNSecInSec should always be true. All functions here will make
24// sure that that is true if it was on all inputs (including *this).
25//
26// The arithmetic and comparison operators are overloaded because they make
27// complete sense and are very useful. The default copy and assignment stuff is
28// left because it works fine. Multiplication and division of Times by Times are
29// not implemented because I can't think of any uses for them and there are
30// multiple ways to do it.
31struct Time {
32 public:
33 static const int32_t kNSecInSec = 1000000000;
34 static const int32_t kNSecInMSec = 1000000;
35 static const int32_t kNSecInUSec = 1000;
36 static const int32_t kMSecInSec = 1000;
37 static const int32_t kUSecInSec = 1000000;
38 Time(int32_t sec, int32_t nsec) : sec_(sec), nsec_(nsec) {
39 Check();
40 }
41 #ifndef SWIG
42 explicit Time(const struct timespec &value)
43 : sec_(value.tv_sec), nsec_(value.tv_nsec) {
44 Check();
45 }
46 struct timespec ToTimespec() const {
47 struct timespec ans;
48 ans.tv_sec = sec_;
49 ans.tv_nsec = nsec_;
50 return ans;
51 }
brians57dd5822013-02-27 21:44:15 +000052 explicit Time(const struct timeval &value)
53 : sec_(value.tv_sec), nsec_(value.tv_usec * kNSecInUSec) {
54 Check();
55 }
56 struct timeval ToTimeval() const {
57 struct timeval ans;
58 ans.tv_sec = sec_;
59 ans.tv_usec = nsec_ / kNSecInUSec;
60 return ans;
61 }
brians343bc112013-02-10 01:53:46 +000062 #endif // SWIG
Brian Silverman3204dd82013-03-12 18:42:01 -070063
brians343bc112013-02-10 01:53:46 +000064 // CLOCK_MONOTONIC on the fitpc and CLOCK_REALTIME on the cRIO because the
65 // cRIO doesn't have any others.
66 // CLOCK_REALTIME is the default realtime clock and CLOCK_MONOTONIC doesn't
67 // change when somebody changes the wall clock (like the ntp deamon or
68 // whatever). See clock_gettime(2) for details.
69 //
70 // This is the clock that code that just wants to sleep for a certain amount
71 // of time or measure how long something takes should use.
72 #ifndef __VXWORKS__
73 static const clockid_t kDefaultClock = CLOCK_MONOTONIC;
74 #else
75 static const clockid_t kDefaultClock = CLOCK_REALTIME;
76 #endif
77 // Creates a Time representing the current value of the specified clock or
78 // dies.
79 static Time Now(clockid_t clock = kDefaultClock);
80
81 // Constructs a Time representing seconds.
82 static Time InSeconds(double seconds) {
83 return Time(static_cast<int32_t>(seconds),
84 (seconds - static_cast<int32_t>(seconds)) * kNSecInSec);
85 }
86
87 // Constructs a time representing microseconds.
88 static Time InNS(int64_t nseconds) {
89 return Time(nseconds / static_cast<int64_t>(kNSecInSec),
90 nseconds % kNSecInSec);
91 }
92
93 // Constructs a time representing microseconds.
94 static Time InUS(int useconds) {
95 return Time(useconds / kUSecInSec, (useconds % kUSecInSec) * kNSecInUSec);
96 }
97
98 // Constructs a time representing mseconds.
99 static Time InMS(int mseconds) {
100 return Time(mseconds / kMSecInSec, (mseconds % kMSecInSec) * kNSecInMSec);
101 }
102
103 // Checks whether or not this time is within amount nanoseconds of other.
104 bool IsWithin(const Time &other, int64_t amount) const;
105
106 // Returns the time represented all in nanoseconds.
107 int64_t ToNSec() const {
108 return static_cast<int64_t>(sec_) * static_cast<int64_t>(kNSecInSec) +
109 static_cast<int64_t>(nsec_);
110 }
111#ifdef __VXWORKS__
112 // Returns the time represented all in system clock ticks. The system clock
113 // rate is retrieved using sysClkRateGet().
114 int ToTicks() const {
115 return ToNSec() / static_cast<int64_t>(kNSecInSec / sysClkRateGet());
116 }
Brian Silverman3204dd82013-03-12 18:42:01 -0700117 // Constructs a Time representing ticks.
Brian Silvermanffe3d712013-03-15 21:35:59 -0700118 // TODO(brians): test this one too
Brian Silverman3204dd82013-03-12 18:42:01 -0700119 static Time InTicks(int ticks) {
Brian Silvermanffe3d712013-03-15 21:35:59 -0700120 return Time::InSeconds(static_cast<double>(ticks) / sysClkRateGet());
Brian Silverman3204dd82013-03-12 18:42:01 -0700121 }
brians343bc112013-02-10 01:53:46 +0000122#endif
123
124 // Returns the time represented in milliseconds.
125 int64_t ToMSec() const {
126 return static_cast<int64_t>(sec_) * static_cast<int64_t>(kMSecInSec) +
127 (static_cast<int64_t>(nsec_) / static_cast<int64_t>(kNSecInMSec));
128 }
129
briansf0165ca2013-03-02 06:17:47 +0000130 // Returns the time represented in fractional seconds.
131 double ToSeconds() const {
132 return static_cast<double>(sec_) + static_cast<double>(nsec_) / kNSecInSec;
133 }
134
brians343bc112013-02-10 01:53:46 +0000135 #ifndef SWIG
136 Time &operator+=(const Time &rhs);
137 Time &operator-=(const Time &rhs);
138 Time &operator*=(int32_t rhs);
139 Time &operator/=(int32_t rhs);
140 Time &operator%=(int32_t rhs);
141 #endif
142 const Time operator+(const Time &rhs) const;
143 const Time operator-(const Time &rhs) const;
144 const Time operator*(int32_t rhs) const;
145 const Time operator/(int32_t rhs) const;
146 const Time operator%(int32_t rhs) const;
147
148 bool operator==(const Time &rhs) const;
149 bool operator!=(const Time &rhs) const;
150 bool operator<(const Time &rhs) const;
151 bool operator>(const Time &rhs) const;
152 bool operator<=(const Time &rhs) const;
153 bool operator>=(const Time &rhs) const;
154
155 #ifndef SWIG
156 // For gtest etc.
157 friend std::ostream &operator<<(std::ostream &os, const Time &time);
158 #endif // SWIG
159
160 int32_t sec() const { return sec_; }
161 void set_sec(int32_t sec) { sec_ = sec; }
162 int32_t nsec() const { return nsec_; }
163 void set_nsec(int32_t nsec) {
164 nsec_ = nsec;
165 Check();
166 }
167
Brian Silverman3204dd82013-03-12 18:42:01 -0700168 // Absolute value.
169 Time abs() const {
170 if (*this > Time(0, 0)) return *this;
171 return Time(-sec_ - 1, kNSecInSec - nsec_);
172 }
173
174 // Enables returning the mock time value for Now instead of checking the
175 // system clock. This should only be used when testing things depending on
176 // time, or many things may/will break.
177 static void EnableMockTime(const Time now);
178 // Sets now when time is being mocked.
179 static void SetMockTime(const Time now);
180 // Convenience function to just increment the mock time by a certain amount.
181 static void IncrementMockTime(const Time amount) {
182 SetMockTime(Now() + amount);
183 }
184 // Disables mocking time.
185 static void DisableMockTime();
186
brians343bc112013-02-10 01:53:46 +0000187 private:
188 int32_t sec_, nsec_;
189 // LOG(FATAL)s if nsec_ is >= kNSecInSec.
190 void Check();
191};
192
193// Sleeps for the amount of time represented by time counted by clock.
194void SleepFor(const Time &time, clockid_t clock = Time::kDefaultClock);
195// Sleeps until clock is at the time represented by time.
196void SleepUntil(const Time &time, clockid_t clock = Time::kDefaultClock);
197
198} // namespace time
199} // namespace aos
200
201#endif // AOS_COMMON_TIME_H_