chrono.hpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // mac/chrono.cpp --------------------------------------------------------------//
  2. // Copyright Beman Dawes 2008
  3. // Copyright 2009-2010 Vicente J. Botet Escriba
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // See http://www.boost.org/LICENSE_1_0.txt
  6. //----------------------------------------------------------------------------//
  7. // Mac //
  8. //----------------------------------------------------------------------------//
  9. #include <sys/time.h> //for gettimeofday and timeval
  10. #include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
  11. #include <boost/assert.hpp>
  12. namespace boost
  13. {
  14. namespace chrono
  15. {
  16. // system_clock
  17. // gettimeofday is the most precise "system time" available on this platform.
  18. // It returns the number of microseconds since New Years 1970 in a struct called timeval
  19. // which has a field for seconds and a field for microseconds.
  20. // Fill in the timeval and then convert that to the time_point
  21. system_clock::time_point
  22. system_clock::now() BOOST_NOEXCEPT
  23. {
  24. timeval tv;
  25. gettimeofday(&tv, 0);
  26. return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
  27. }
  28. #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
  29. system_clock::time_point
  30. system_clock::now(system::error_code & ec)
  31. {
  32. timeval tv;
  33. gettimeofday(&tv, 0);
  34. if (!::boost::chrono::is_throws(ec))
  35. {
  36. ec.clear();
  37. }
  38. return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
  39. }
  40. #endif
  41. // Take advantage of the fact that on this platform time_t is nothing but
  42. // an integral count of seconds since New Years 1970 (same epoch as timeval).
  43. // Just get the duration out of the time_point and truncate it to seconds.
  44. time_t
  45. system_clock::to_time_t(const time_point& t) BOOST_NOEXCEPT
  46. {
  47. return time_t(duration_cast<seconds>(t.time_since_epoch()).count());
  48. }
  49. // Just turn the time_t into a count of seconds and construct a time_point with it.
  50. system_clock::time_point
  51. system_clock::from_time_t(time_t t) BOOST_NOEXCEPT
  52. {
  53. return system_clock::time_point(seconds(t));
  54. }
  55. namespace chrono_detail
  56. {
  57. // steady_clock
  58. // Note, in this implementation steady_clock and high_resolution_clock
  59. // are the same clock. They are both based on mach_absolute_time().
  60. // mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
  61. // nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom
  62. // are run time constants supplied by the OS. This clock has no relationship
  63. // to the Gregorian calendar. It's main use is as a high resolution timer.
  64. // MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize
  65. // for that case as an optimization.
  66. BOOST_CHRONO_STATIC
  67. steady_clock::rep
  68. steady_simplified()
  69. {
  70. return mach_absolute_time();
  71. }
  72. #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
  73. BOOST_CHRONO_STATIC
  74. steady_clock::rep
  75. steady_simplified_ec(system::error_code & ec)
  76. {
  77. if (!::boost::chrono::is_throws(ec))
  78. {
  79. ec.clear();
  80. }
  81. return mach_absolute_time();
  82. }
  83. #endif
  84. BOOST_CHRONO_STATIC
  85. double
  86. compute_steady_factor(kern_return_t& err)
  87. {
  88. mach_timebase_info_data_t MachInfo;
  89. err = mach_timebase_info(&MachInfo);
  90. if ( err != 0 ) {
  91. return 0;
  92. }
  93. return static_cast<double>(MachInfo.numer) / MachInfo.denom;
  94. }
  95. BOOST_CHRONO_STATIC
  96. steady_clock::rep
  97. steady_full()
  98. {
  99. kern_return_t err;
  100. const double factor = chrono_detail::compute_steady_factor(err);
  101. if (err != 0)
  102. {
  103. BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
  104. }
  105. return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
  106. }
  107. #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
  108. BOOST_CHRONO_STATIC
  109. steady_clock::rep
  110. steady_full_ec(system::error_code & ec)
  111. {
  112. kern_return_t err;
  113. const double factor = chrono_detail::compute_steady_factor(err);
  114. if (err != 0)
  115. {
  116. if (::boost::chrono::is_throws(ec))
  117. {
  118. boost::throw_exception(
  119. system::system_error(
  120. err,
  121. ::boost::system::system_category(),
  122. "chrono::steady_clock" ));
  123. }
  124. else
  125. {
  126. ec.assign( errno, ::boost::system::system_category() );
  127. return steady_clock::rep();
  128. }
  129. }
  130. if (!::boost::chrono::is_throws(ec))
  131. {
  132. ec.clear();
  133. }
  134. return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
  135. }
  136. #endif
  137. typedef steady_clock::rep (*FP)();
  138. #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
  139. typedef steady_clock::rep (*FP_ec)(system::error_code &);
  140. #endif
  141. BOOST_CHRONO_STATIC
  142. FP
  143. init_steady_clock(kern_return_t & err)
  144. {
  145. mach_timebase_info_data_t MachInfo;
  146. err = mach_timebase_info(&MachInfo);
  147. if ( err != 0 )
  148. {
  149. return 0;
  150. }
  151. if (MachInfo.numer == MachInfo.denom)
  152. {
  153. return &chrono_detail::steady_simplified;
  154. }
  155. return &chrono_detail::steady_full;
  156. }
  157. #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
  158. BOOST_CHRONO_STATIC
  159. FP_ec
  160. init_steady_clock_ec(kern_return_t & err)
  161. {
  162. mach_timebase_info_data_t MachInfo;
  163. err = mach_timebase_info(&MachInfo);
  164. if ( err != 0 )
  165. {
  166. return 0;
  167. }
  168. if (MachInfo.numer == MachInfo.denom)
  169. {
  170. return &chrono_detail::steady_simplified_ec;
  171. }
  172. return &chrono_detail::steady_full_ec;
  173. }
  174. #endif
  175. }
  176. steady_clock::time_point
  177. steady_clock::now() BOOST_NOEXCEPT
  178. {
  179. kern_return_t err;
  180. chrono_detail::FP fp = chrono_detail::init_steady_clock(err);
  181. if ( err != 0 )
  182. {
  183. BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
  184. }
  185. return time_point(duration(fp()));
  186. }
  187. #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
  188. steady_clock::time_point
  189. steady_clock::now(system::error_code & ec)
  190. {
  191. kern_return_t err;
  192. chrono_detail::FP_ec fp = chrono_detail::init_steady_clock_ec(err);
  193. if ( err != 0 )
  194. {
  195. if (::boost::chrono::is_throws(ec))
  196. {
  197. boost::throw_exception(
  198. system::system_error(
  199. err,
  200. ::boost::system::system_category(),
  201. "chrono::steady_clock" ));
  202. }
  203. else
  204. {
  205. ec.assign( err, ::boost::system::system_category() );
  206. return time_point();
  207. }
  208. }
  209. if (!::boost::chrono::is_throws(ec))
  210. {
  211. ec.clear();
  212. }
  213. return time_point(duration(fp(ec)));
  214. }
  215. #endif
  216. } // namespace chrono
  217. } // namespace boost