$search
00001 #ifndef RTC_DURATION_H_ 00002 #define RTC_DURATION_H_ 00003 00004 #include "rtc/rtcBase.h" 00005 #include <iostream> 00006 #include <math.h> 00007 #include <stdexcept> 00008 #include <climits> 00009 00010 #ifdef WIN32 00011 #include <windows.h> 00012 #endif 00013 00014 namespace rtc { 00015 00016 inline void normalizeSecNSecSigned(int64_t& sec, int64_t& nsec) 00017 { 00018 int64_t nsec_part = nsec; 00019 int64_t sec_part = sec; 00020 00021 while (nsec_part > 1000000000L) 00022 { 00023 nsec_part -= 1000000000L; 00024 ++sec_part; 00025 } 00026 while (nsec_part < 0) 00027 { 00028 nsec_part += 1000000000L; 00029 --sec_part; 00030 } 00031 00032 if (sec_part < INT_MIN || sec_part > INT_MAX) 00033 throw std::runtime_error("Duration is out of dual 32-bit range"); 00034 00035 sec = sec_part; 00036 nsec = nsec_part; 00037 } 00038 00039 inline void normalizeSecNSecSigned(int32_t& sec, int32_t& nsec) 00040 { 00041 int64_t sec64 = sec; 00042 int64_t nsec64 = nsec; 00043 00044 normalizeSecNSecSigned(sec64, nsec64); 00045 00046 sec = (int32_t)sec64; 00047 nsec = (int32_t)nsec64; 00048 } 00049 00050 template<class T> 00051 class DurationBase 00052 { 00053 public: 00054 int32_t sec, nsec; 00055 DurationBase() : sec(0), nsec(0) { } 00056 DurationBase(int32_t _sec, int32_t _nsec); 00057 explicit DurationBase(double t){fromSec(t);}; 00058 ~DurationBase() {} 00059 T operator+(const T &rhs) const; 00060 T operator-(const T &rhs) const; 00061 T operator-() const; 00062 T operator*(double scale) const; 00063 T& operator+=(const T &rhs); 00064 T& operator-=(const T &rhs); 00065 T& operator*=(double scale); 00066 bool operator==(const T &rhs) const; 00067 inline bool operator!=(const T &rhs) const { return !(*static_cast<const T*>(this) == rhs); } 00068 bool operator>(const T &rhs) const; 00069 bool operator<(const T &rhs) const; 00070 bool operator>=(const T &rhs) const; 00071 bool operator<=(const T &rhs) const; 00072 double toSec() const { return (double)sec + 1e-9*(double)nsec; }; 00073 int64_t toNSec() const {return (int64_t)sec*1000000000ll + (int64_t)nsec; }; 00074 T& fromSec(double t); 00075 T& fromNSec(int64_t t); 00076 bool isZero(); 00077 }; 00078 00079 class Duration : public DurationBase<Duration> 00080 { 00081 public: 00082 Duration() 00083 : DurationBase<Duration>() 00084 { } 00085 00086 Duration(int32_t _sec, int32_t _nsec) 00087 : DurationBase<Duration>(_sec, _nsec) 00088 {} 00089 00090 explicit Duration(double t) { fromSec(t); } 00091 00095 bool sleep() const; 00096 }; 00097 00098 extern const Duration DURATION_MAX; 00099 extern const Duration DURATION_MIN; 00100 00101 class WallDuration : public DurationBase<WallDuration> 00102 { 00103 public: 00104 WallDuration() 00105 : DurationBase<WallDuration>() 00106 { } 00107 00108 WallDuration(int32_t _sec, int32_t _nsec) 00109 : DurationBase<WallDuration>(_sec, _nsec) 00110 {} 00111 00112 explicit WallDuration(double t) { fromSec(t); } 00113 00117 bool sleep() const; 00118 }; 00119 00120 std::ostream &operator <<(std::ostream &os, const Duration &rhs); 00121 std::ostream &operator <<(std::ostream &os, const WallDuration &rhs); 00122 00123 // 00124 // DurationBase template member function implementation 00125 // 00126 template<class T> 00127 DurationBase<T>::DurationBase(int32_t _sec, int32_t _nsec) 00128 : sec(_sec), nsec(_nsec) 00129 { 00130 normalizeSecNSecSigned(sec, nsec); 00131 } 00132 00133 template<class T> 00134 T& DurationBase<T>::fromSec(double d) 00135 { 00136 #ifdef HAVE_TRUNC 00137 sec = (int32_t)trunc(d); 00138 #else 00139 // (morgan: why doesn't win32 provide trunc? argh. hacked this together 00140 // without much thought. need to test this conversion. 00141 if (d >= 0.0) 00142 sec = (int32_t)floor(d); 00143 else 00144 sec = (int32_t)floor(d) + 1; 00145 #endif 00146 nsec = (int32_t)((d - (double)sec)*1000000000); 00147 return *static_cast<T*>(this); 00148 } 00149 00150 template<class T> 00151 T& DurationBase<T>::fromNSec(int64_t t) 00152 { 00153 sec = (int32_t)(t / 1000000000); 00154 nsec = (int32_t)(t % 1000000000); 00155 00156 normalizeSecNSecSigned(sec, nsec); 00157 00158 return *static_cast<T*>(this); 00159 } 00160 00161 template<class T> 00162 T DurationBase<T>::operator+(const T &rhs) const 00163 { 00164 return T(sec + rhs.sec, nsec + rhs.nsec); 00165 } 00166 00167 template<class T> 00168 T DurationBase<T>::operator*(double scale) const 00169 { 00170 return T(toSec() * scale); 00171 } 00172 00173 template<class T> 00174 T DurationBase<T>::operator-(const T &rhs) const 00175 { 00176 return T(sec - rhs.sec, nsec - rhs.nsec); 00177 } 00178 00179 template<class T> 00180 T DurationBase<T>::operator-() const 00181 { 00182 return T(-sec , -nsec); 00183 } 00184 00185 template<class T> 00186 T& DurationBase<T>::operator+=(const T &rhs) 00187 { 00188 *this = *this + rhs; 00189 return *static_cast<T*>(this); 00190 } 00191 00192 template<class T> 00193 T& DurationBase<T>::operator-=(const T &rhs) 00194 { 00195 *this += (-rhs); 00196 return *static_cast<T*>(this); 00197 } 00198 00199 template<class T> 00200 T& DurationBase<T>::operator*=(double scale) 00201 { 00202 fromSec(toSec() * scale); 00203 return *static_cast<T*>(this); 00204 } 00205 00206 template<class T> 00207 bool DurationBase<T>::operator<(const T &rhs) const 00208 { 00209 if (sec < rhs.sec) 00210 return true; 00211 else if (sec == rhs.sec && nsec < rhs.nsec) 00212 return true; 00213 return false; 00214 } 00215 00216 template<class T> 00217 bool DurationBase<T>::operator>(const T &rhs) const 00218 { 00219 if (sec > rhs.sec) 00220 return true; 00221 else if (sec == rhs.sec && nsec > rhs.nsec) 00222 return true; 00223 return false; 00224 } 00225 00226 template<class T> 00227 bool DurationBase<T>::operator<=(const T &rhs) const 00228 { 00229 if (sec < rhs.sec) 00230 return true; 00231 else if (sec == rhs.sec && nsec <= rhs.nsec) 00232 return true; 00233 return false; 00234 } 00235 00236 template<class T> 00237 bool DurationBase<T>::operator>=(const T &rhs) const 00238 { 00239 if (sec > rhs.sec) 00240 return true; 00241 else if (sec == rhs.sec && nsec >= rhs.nsec) 00242 return true; 00243 return false; 00244 } 00245 00246 template<class T> 00247 bool DurationBase<T>::operator==(const T &rhs) const 00248 { 00249 return sec == rhs.sec && nsec == rhs.nsec; 00250 } 00251 00252 template<class T> 00253 bool DurationBase<T>::isZero() 00254 { 00255 return sec == 0 && nsec == 0; 00256 } 00257 00258 } // namespace rtc 00259 00260 #endif // RTC_DURATION_H_