Go to the documentation of this file.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
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
00140
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 }
00259
00260 #endif // RTC_DURATION_H_