$search
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); // carry handled in ctor 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 // Throws an exception if we go out of 32-bit range 00177 normalizeSecNSecUnsigned(sec_sum, nsec_sum); 00178 00179 // now, it's safe to downcast back to uint32 bits 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 } // namespace rtc 00245 00246 #endif // RTC_TIME_H_