00001 #ifndef RTC_TIME_H_
00002 #define RTC_TIME_H_
00003
00004 #include "rtc/rtcBase.h"
00005 #include "rtc/rtcDuration.h"
00006
00007 #include <iostream>
00008 #include <math.h>
00009
00010 #ifdef WIN32
00011 #include <windows.h>
00012 #endif
00013
00014 namespace rtc {
00015
00016 inline void normalizeSecNSec(uint64_t& sec, uint64_t& nsec)
00017 {
00018 uint64_t nsec_part = nsec % 1000000000UL;
00019 uint64_t sec_part = nsec / 1000000000UL;
00020
00021 if (sec_part > UINT_MAX)
00022 throw std::runtime_error("Time is out of dual 32-bit range");
00023
00024 sec += sec_part;
00025 nsec = nsec_part;
00026 }
00027
00028 inline void normalizeSecNSec(uint32_t& sec, uint32_t& nsec)
00029 {
00030 uint64_t sec64 = sec;
00031 uint64_t nsec64 = nsec;
00032
00033 normalizeSecNSec(sec64, nsec64);
00034
00035 sec = (uint32_t)sec64;
00036 nsec = (uint32_t)nsec64;
00037 }
00038
00039 inline void normalizeSecNSecUnsigned(int64_t& sec, int64_t& nsec)
00040 {
00041 int64_t nsec_part = nsec;
00042 int64_t sec_part = sec;
00043
00044 while (nsec_part >= 1000000000L)
00045 {
00046 nsec_part -= 1000000000L;
00047 ++sec_part;
00048 }
00049 while (nsec_part < 0)
00050 {
00051 nsec_part += 1000000000L;
00052 --sec_part;
00053 }
00054
00055 if (sec_part < 0 || sec_part > INT_MAX)
00056 throw std::runtime_error("Time is out of dual 32-bit range");
00057
00058 sec = sec_part;
00059 nsec = nsec_part;
00060 }
00061
00062 template<class T, class D>
00063 class TimeBase
00064 {
00065 public:
00066 uint32_t sec, nsec;
00067
00068 TimeBase() : sec(0), nsec(0) { }
00069 TimeBase(uint32_t _sec, uint32_t _nsec) : sec(_sec), nsec(_nsec)
00070 {
00071 normalizeSecNSec(sec, nsec);
00072 }
00073 explicit TimeBase(double t) { fromSec(t); }
00074 ~TimeBase() {}
00075 D operator-(const T &rhs) const;
00076 T operator+(const D &rhs) const;
00077 T operator-(const D &rhs) const;
00078 T& operator+=(const D &rhs);
00079 T& operator-=(const D &rhs);
00080 bool operator==(const T &rhs) const;
00081 inline bool operator!=(const T &rhs) const { return !(*static_cast<const T*>(this) == rhs); }
00082 bool operator>(const T &rhs) const;
00083 bool operator<(const T &rhs) const;
00084 bool operator>=(const T &rhs) const;
00085 bool operator<=(const T &rhs) const;
00086
00087 double toSec() const { return (double)sec + 1e-9*(double)nsec; };
00088 T& fromSec(double t) { sec = (uint32_t)floor(t); nsec = (uint32_t)round((t-sec) * 1e9); return *static_cast<T*>(this);}
00089
00090 uint64_t toNSec() const {return (uint64_t)sec*1000000000ull + (uint64_t)nsec; }
00091 T& fromNSec(uint64_t t);
00092
00093 inline bool isZero() const { return sec == 0 && nsec == 0; }
00094 inline bool is_zero() const { return isZero(); }
00095 };
00096
00097 class Time : public TimeBase<Time, Duration>
00098 {
00099 public:
00100 Time()
00101 : TimeBase<Time, Duration>()
00102 {}
00103
00104 Time(uint32_t _sec, uint32_t _nsec)
00105 : TimeBase<Time, Duration>(_sec, _nsec)
00106 {}
00107
00108 explicit Time(double t) { fromSec(t); }
00109
00110 static Time now();
00111 static bool sleepUntil(const Time& end);
00112
00113 static void init();
00114 static void shutdown();
00115 static void setNow(const Time& new_now);
00116 static bool useSystemTime() { return use_system_time_; }
00117 private:
00118 static Time sim_time_;
00119 static bool use_system_time_;
00120 };
00121
00122 static const Time TIME_MAX = rtc::Time(UINT_MAX, 999999999);
00123 static const Time TIME_MIN = rtc::Time(0, 0);
00124
00125 class WallTime : public TimeBase<WallTime, WallDuration>
00126 {
00127 public:
00128 WallTime()
00129 : TimeBase<WallTime, WallDuration>()
00130 {}
00131
00132 WallTime(uint32_t _sec, uint32_t _nsec)
00133 : TimeBase<WallTime, WallDuration>(_sec, _nsec)
00134 {}
00135
00136 explicit WallTime(double t) { fromSec(t); }
00137
00138 static WallTime now();
00139
00140 static bool sleepUntil(const WallTime& end);
00141 };
00142
00143 std::ostream &operator <<(std::ostream &os, const Time &rhs);
00144 std::ostream &operator <<(std::ostream &os, const WallTime &rhs);
00145
00146 template<class T, class D>
00147 T& TimeBase<T, D>::fromNSec(uint64_t t)
00148 {
00149 sec = (int32_t)(t / 1000000000);
00150 nsec = (int32_t)(t % 1000000000);
00151
00152 normalizeSecNSec(sec, nsec);
00153
00154 return *static_cast<T*>(this);
00155 }
00156
00157 template<class T, class D>
00158 D TimeBase<T, D>::operator-(const T &rhs) const
00159 {
00160 return D((int32_t)sec - (int32_t)rhs.sec,
00161 (int32_t)nsec - (int32_t)rhs.nsec);
00162 }
00163
00164 template<class T, class D>
00165 T TimeBase<T, D>::operator-(const D &rhs) const
00166 {
00167 return *static_cast<const T*>(this) + ( -rhs);
00168 }
00169
00170 template<class T, class D>
00171 T TimeBase<T, D>::operator+(const D &rhs) const
00172 {
00173 int64_t sec_sum = (int64_t)sec + (int64_t)rhs.sec;
00174 int64_t nsec_sum = (int64_t)nsec + (int64_t)rhs.nsec;
00175
00176
00177 normalizeSecNSecUnsigned(sec_sum, nsec_sum);
00178
00179
00180 return T((uint32_t)sec_sum, (uint32_t)nsec_sum);
00181 }
00182
00183 template<class T, class D>
00184 T& TimeBase<T, D>::operator+=(const D &rhs)
00185 {
00186 *this = *this + rhs;
00187 return *static_cast<T*>(this);
00188 }
00189
00190 template<class T, class D>
00191 T& TimeBase<T, D>::operator-=(const D &rhs)
00192 {
00193 *this += (-rhs);
00194 return *static_cast<T*>(this);
00195 }
00196
00197 template<class T, class D>
00198 bool TimeBase<T, D>::operator==(const T &rhs) const
00199 {
00200 return sec == rhs.sec && nsec == rhs.nsec;
00201 }
00202
00203 template<class T, class D>
00204 bool TimeBase<T, D>::operator<(const T &rhs) const
00205 {
00206 if (sec < rhs.sec)
00207 return true;
00208 else if (sec == rhs.sec && nsec < rhs.nsec)
00209 return true;
00210 return false;
00211 }
00212
00213 template<class T, class D>
00214 bool TimeBase<T, D>::operator>(const T &rhs) const
00215 {
00216 if (sec > rhs.sec)
00217 return true;
00218 else if (sec == rhs.sec && nsec > rhs.nsec)
00219 return true;
00220 return false;
00221 }
00222
00223 template<class T, class D>
00224 bool TimeBase<T, D>::operator<=(const T &rhs) const
00225 {
00226 if (sec < rhs.sec)
00227 return true;
00228 else if (sec == rhs.sec && nsec <= rhs.nsec)
00229 return true;
00230 return false;
00231 }
00232
00233 template<class T, class D>
00234 bool TimeBase<T, D>::operator>=(const T &rhs) const
00235 {
00236 if (sec > rhs.sec)
00237 return true;
00238 else if (sec == rhs.sec && nsec >= rhs.nsec)
00239 return true;
00240 return false;
00241 }
00242
00243
00244 }
00245
00246 #endif // RTC_TIME_H_