time.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // POSIX time-related utilities
  2. //
  3. // Platform: ISO C++ 98/11 - POSIX
  4. // $Id$
  5. #ifndef __VIC_POSIX_TIME_H
  6. #define __VIC_POSIX_TIME_H
  7. #include<__vic/posix/_cfg.h>
  8. #include<__vic/defs.h>
  9. #include<time.h>
  10. #if __cplusplus >= 201103L && !defined(__VIC_HAVE_STD_CHRONO)
  11. #define __VIC_HAVE_STD_CHRONO 1
  12. #endif
  13. #ifdef __VIC_HAVE_STD_CHRONO
  14. #include<chrono>
  15. #endif
  16. namespace __vic { namespace posix {
  17. using ::time_t;
  18. //////////////////////////////////////////////////////////////////////////////
  19. struct time_spec : ::timespec
  20. {
  21. // Unit tags
  22. enum sec_units { sec };
  23. enum msec_units { msec };
  24. enum usec_units { usec };
  25. enum nsec_units { nsec };
  26. time_spec() __VIC_DEFAULT_CTR
  27. time_spec(time_t secs, long nsecs) { tv_sec = secs; tv_nsec = nsecs; }
  28. time_spec(time_t secs, sec_units)
  29. {
  30. tv_sec = secs;
  31. tv_nsec = 0;
  32. }
  33. time_spec(time_t msecs, msec_units)
  34. {
  35. tv_sec = msecs / 1000;
  36. tv_nsec = msecs % 1000 * 1000000L;
  37. }
  38. time_spec(time_t usecs, usec_units)
  39. {
  40. tv_sec = usecs / 1000000UL;
  41. tv_nsec = usecs % 1000000UL * 1000000L;
  42. }
  43. time_spec(time_t nsecs, nsec_units)
  44. {
  45. tv_sec = nsecs / 1000000000UL;
  46. tv_nsec = nsecs % 1000000000UL;
  47. }
  48. #ifdef __VIC_HAVE_STD_CHRONO
  49. template<class Rep, class Period>
  50. time_spec(const std::chrono::duration<Rep,Period> &d)
  51. {
  52. auto sec = std::chrono::duration_cast<std::chrono::seconds>(d);
  53. auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(d - sec);
  54. tv_sec = sec.count();
  55. tv_nsec = ns.count();
  56. }
  57. time_spec(const std::chrono::seconds &secs)
  58. : time_spec(secs.count(), sec) {}
  59. time_spec(const std::chrono::nanoseconds &nsecs)
  60. : time_spec(nsecs.count(), nsec) {}
  61. operator std::chrono::nanoseconds() const
  62. {
  63. return std::chrono::nanoseconds(tv_nsec +
  64. std::chrono::nanoseconds::rep(tv_sec) * 1000000000UL);
  65. }
  66. template<class Rep, class Period>
  67. time_spec &operator+=(const std::chrono::duration<Rep,Period> &d)
  68. {
  69. auto sec = std::chrono::duration_cast<std::chrono::seconds>(d);
  70. auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(d - sec);
  71. tv_sec += sec;
  72. tv_nsec += ns;
  73. normalize_big();
  74. return *this;
  75. }
  76. template<class Rep, class Period>
  77. time_spec &operator-=(const std::chrono::duration<Rep,Period> &d)
  78. {
  79. auto sec = std::chrono::duration_cast<std::chrono::seconds>(d);
  80. auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(d - sec);
  81. tv_sec -= sec;
  82. tv_nsec -= ns;
  83. normalize_small();
  84. return *this;
  85. }
  86. time_spec &operator+=(const std::chrono::seconds &secs)
  87. {
  88. tv_sec += secs.count();
  89. return *this;
  90. }
  91. time_spec &operator-=(const std::chrono::seconds &secs)
  92. {
  93. tv_sec -= secs.count();
  94. return *this;
  95. }
  96. #endif
  97. time_spec &operator+=(const time_spec &t)
  98. {
  99. tv_sec += t.tv_sec;
  100. tv_nsec += t.tv_nsec;
  101. normalize_big();
  102. return *this;
  103. }
  104. time_spec &operator-=(const time_spec &t)
  105. {
  106. tv_sec -= t.tv_sec;
  107. tv_nsec -= t.tv_nsec;
  108. normalize_small();
  109. return *this;
  110. }
  111. private:
  112. void normalize_big()
  113. { if(tv_nsec >= 1000000000L) { tv_sec++; tv_nsec -= 1000000000L; } }
  114. void normalize_small()
  115. { if(tv_nsec < 0L) { tv_sec--; tv_nsec += 1000000000L; } }
  116. };
  117. //////////////////////////////////////////////////////////////////////////////
  118. //----------------------------------------------------------------------------
  119. inline bool operator==(const time_spec &t1, const time_spec &t2)
  120. {
  121. return t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec;
  122. }
  123. //----------------------------------------------------------------------------
  124. inline bool operator!=(const time_spec &t1, const time_spec &t2)
  125. {
  126. return !(t1 == t2);
  127. }
  128. //----------------------------------------------------------------------------
  129. inline bool operator<(const time_spec &t1, const time_spec &t2)
  130. {
  131. return t1.tv_sec < t2.tv_sec ||
  132. (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec);
  133. }
  134. //----------------------------------------------------------------------------
  135. inline bool operator>(const time_spec &t1, const time_spec &t2)
  136. {
  137. return t1.tv_sec > t2.tv_sec ||
  138. (t1.tv_sec == t2.tv_sec && t1.tv_nsec > t2.tv_nsec);
  139. }
  140. //----------------------------------------------------------------------------
  141. inline bool operator<=(const time_spec &t1, const time_spec &t2)
  142. {
  143. return t1.tv_sec < t2.tv_sec ||
  144. (t1.tv_sec == t2.tv_sec && t1.tv_nsec <= t2.tv_nsec);
  145. }
  146. //----------------------------------------------------------------------------
  147. inline bool operator>=(const time_spec &t1, const time_spec &t2)
  148. {
  149. return t1.tv_sec > t2.tv_sec ||
  150. (t1.tv_sec == t2.tv_sec && t1.tv_nsec >= t2.tv_nsec);
  151. }
  152. //----------------------------------------------------------------------------
  153. inline time_spec operator+(time_spec t1, const time_spec &t2)
  154. {
  155. return t1 += t2;
  156. }
  157. //----------------------------------------------------------------------------
  158. inline time_spec operator-(time_spec t1, const time_spec &t2)
  159. {
  160. return t1 -= t2;
  161. }
  162. //----------------------------------------------------------------------------
  163. #if _POSIX_TIMERS > 0
  164. using ::clockid_t;
  165. template<clockid_t > struct clock; // not implemented
  166. //////////////////////////////////////////////////////////////////////////////
  167. struct clock_base // internal implementation type
  168. {
  169. #ifdef __VIC_HAVE_STD_CHRONO
  170. using duration = std::chrono::nanoseconds;
  171. using period = duration::period;
  172. using rep = duration::rep;
  173. #endif
  174. protected:
  175. static time_spec get_time_(clockid_t );
  176. };
  177. //////////////////////////////////////////////////////////////////////////////
  178. template<clockid_t ClockID, bool Steady = false>
  179. struct clock_impl : public clock_base // internal implementation type
  180. {
  181. static __VIC_CONSTEXPR_VAR clockid_t id = ClockID;
  182. static __VIC_CONSTEXPR_VAR bool is_steady = Steady;
  183. #ifdef __VIC_HAVE_STD_CHRONO
  184. using time_point = std::chrono::time_point<clock<ClockID>, duration>;
  185. static time_point now() { return time_point(get_time()); }
  186. #endif
  187. static time_spec get_time() { return get_time_(id); }
  188. };
  189. //////////////////////////////////////////////////////////////////////////////
  190. template<> struct clock<CLOCK_REALTIME> : clock_impl<CLOCK_REALTIME> {};
  191. typedef clock<CLOCK_REALTIME> realtime_clock;
  192. #ifdef _POSIX_MONOTONIC_CLOCK
  193. template<> struct clock<CLOCK_MONOTONIC> : clock_impl<CLOCK_MONOTONIC, true> {};
  194. typedef clock<CLOCK_MONOTONIC> monotonic_clock;
  195. #endif
  196. //////////////////////////////////////////////////////////////////////////////
  197. //----------------------------------------------------------------------------
  198. inline time_spec nanoseconds_since_epoch()
  199. {
  200. return realtime_clock::get_time();
  201. }
  202. //----------------------------------------------------------------------------
  203. #else
  204. time_spec nanoseconds_since_epoch();
  205. #endif // _POSIX_TIMERS
  206. }} // namespace
  207. #endif // header guard