PageRenderTime 69ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/third_party/boost-1.60.0/libs/timer/src/cpu_timer.cpp

https://gitlab.com/0072016/0072016-ApplePayDevice-
C++ | 261 lines | 212 code | 33 blank | 16 comment | 26 complexity | eb2680a7f56494fa2fe294da14813ff8 MD5 | raw file
  1. // boost cpu_timer.cpp ---------------------------------------------------------------//
  2. // Copyright Beman Dawes 1994-2006, 2011
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. // See http://www.boost.org/libs/timer for documentation.
  6. //--------------------------------------------------------------------------------------//
  7. // define BOOST_TIMER_SOURCE so that <boost/timer/config.hpp> knows
  8. // the library is being built (possibly exporting rather than importing code)
  9. #define BOOST_TIMER_SOURCE
  10. #include <boost/timer/timer.hpp>
  11. #include <boost/chrono/chrono.hpp>
  12. #include <boost/io/ios_state.hpp>
  13. #include <boost/throw_exception.hpp>
  14. #include <boost/cerrno.hpp>
  15. #include <cstring>
  16. #include <sstream>
  17. #include <cassert>
  18. # if defined(BOOST_WINDOWS_API)
  19. # include <windows.h>
  20. # elif defined(BOOST_POSIX_API)
  21. # include <unistd.h>
  22. # include <sys/times.h>
  23. # else
  24. # error unknown API
  25. # endif
  26. using boost::timer::nanosecond_type;
  27. using boost::timer::cpu_times;
  28. using boost::system::error_code;
  29. namespace
  30. {
  31. void show_time(const cpu_times& times,
  32. std::ostream& os, const std::string& fmt, short places)
  33. // NOTE WELL: Will truncate least-significant digits to LDBL_DIG, which may
  34. // be as low as 10, although will be 15 for many common platforms.
  35. {
  36. if (places > 9)
  37. places = 9;
  38. else if (places < 0)
  39. places = boost::timer::default_places;
  40. boost::io::ios_flags_saver ifs(os);
  41. boost::io::ios_precision_saver ips(os);
  42. os.setf(std::ios_base::fixed, std::ios_base::floatfield);
  43. os.precision(places);
  44. const double sec = 1000000000.0L;
  45. nanosecond_type total = times.system + times.user;
  46. double wall_sec = static_cast<double>(times.wall) / sec;
  47. double total_sec = static_cast<double>(total) / sec;
  48. for (const char* format = fmt.c_str(); *format; ++format)
  49. {
  50. if (*format != '%' || !*(format+1) || !std::strchr("wustp", *(format+1)))
  51. os << *format; // anything except % followed by a valid format character
  52. // gets sent to the output stream
  53. else
  54. {
  55. ++format;
  56. switch (*format)
  57. {
  58. case 'w':
  59. os << wall_sec;
  60. break;
  61. case 'u':
  62. os << static_cast<double>(times.user) / sec;
  63. break;
  64. case 's':
  65. os << static_cast<double>(times.system) / sec;
  66. break;
  67. case 't':
  68. os << total_sec;
  69. break;
  70. case 'p':
  71. os.precision(1);
  72. if (wall_sec > 0.001L && total_sec > 0.001L)
  73. os << (total_sec/wall_sec) * 100.0;
  74. else
  75. os << "n/a";
  76. os.precision(places);
  77. break;
  78. }
  79. }
  80. }
  81. }
  82. # if defined(BOOST_POSIX_API)
  83. boost::int_least64_t tick_factor() // multiplier to convert ticks
  84. // to nanoseconds; -1 if unknown
  85. {
  86. static boost::int_least64_t tick_factor = 0;
  87. if (!tick_factor)
  88. {
  89. if ((tick_factor = ::sysconf(_SC_CLK_TCK)) <= 0)
  90. tick_factor = -1;
  91. else
  92. {
  93. assert(tick_factor <= 1000000000LL); // logic doesn't handle large ticks
  94. tick_factor = 1000000000LL / tick_factor; // compute factor
  95. if (!tick_factor)
  96. tick_factor = -1;
  97. }
  98. }
  99. return tick_factor;
  100. }
  101. # endif
  102. void get_cpu_times(boost::timer::cpu_times& current)
  103. {
  104. boost::chrono::duration<boost::int64_t, boost::nano>
  105. x (boost::chrono::high_resolution_clock::now().time_since_epoch());
  106. current.wall = x.count();
  107. # if defined(BOOST_WINDOWS_API)
  108. FILETIME creation, exit;
  109. if (::GetProcessTimes(::GetCurrentProcess(), &creation, &exit,
  110. (LPFILETIME)&current.system, (LPFILETIME)&current.user))
  111. {
  112. current.user *= 100; // Windows uses 100 nanosecond ticks
  113. current.system *= 100;
  114. }
  115. else
  116. {
  117. current.system = current.user = boost::timer::nanosecond_type(-1);
  118. }
  119. # else
  120. tms tm;
  121. clock_t c = ::times(&tm);
  122. if (c == static_cast<clock_t>(-1)) // error
  123. {
  124. current.system = current.user = boost::timer::nanosecond_type(-1);
  125. }
  126. else
  127. {
  128. current.system = boost::timer::nanosecond_type(tm.tms_stime + tm.tms_cstime);
  129. current.user = boost::timer::nanosecond_type(tm.tms_utime + tm.tms_cutime);
  130. boost::int_least64_t factor;
  131. if ((factor = tick_factor()) != -1)
  132. {
  133. current.user *= factor;
  134. current.system *= factor;
  135. }
  136. else
  137. {
  138. current.user = current.system = boost::timer::nanosecond_type(-1);
  139. }
  140. }
  141. # endif
  142. }
  143. // CAUTION: must be identical to same constant in auto_timers_construction.cpp
  144. const std::string default_fmt(" %ws wall, %us user + %ss system = %ts CPU (%p%)\n");
  145. } // unnamed namespace
  146. namespace boost
  147. {
  148. namespace timer
  149. {
  150. // format ------------------------------------------------------------------------//
  151. BOOST_TIMER_DECL
  152. std::string format(const cpu_times& times, short places, const std::string& fmt)
  153. {
  154. std::stringstream ss;
  155. ss.exceptions(std::ios_base::badbit | std::ios_base::failbit);
  156. show_time(times, ss, fmt, places);
  157. return ss.str();
  158. }
  159. BOOST_TIMER_DECL
  160. std::string format(const cpu_times& times, short places)
  161. {
  162. return format(times, places, default_fmt);
  163. }
  164. // cpu_timer ---------------------------------------------------------------------//
  165. void cpu_timer::start() BOOST_NOEXCEPT
  166. {
  167. m_is_stopped = false;
  168. get_cpu_times(m_times);
  169. }
  170. void cpu_timer::stop() BOOST_NOEXCEPT
  171. {
  172. if (is_stopped())
  173. return;
  174. m_is_stopped = true;
  175. cpu_times current;
  176. get_cpu_times(current);
  177. m_times.wall = (current.wall - m_times.wall);
  178. m_times.user = (current.user - m_times.user);
  179. m_times.system = (current.system - m_times.system);
  180. }
  181. cpu_times cpu_timer::elapsed() const BOOST_NOEXCEPT
  182. {
  183. if (is_stopped())
  184. return m_times;
  185. cpu_times current;
  186. get_cpu_times(current);
  187. current.wall -= m_times.wall;
  188. current.user -= m_times.user;
  189. current.system -= m_times.system;
  190. return current;
  191. }
  192. void cpu_timer::resume() BOOST_NOEXCEPT
  193. {
  194. if (is_stopped())
  195. {
  196. cpu_times current (m_times);
  197. start();
  198. m_times.wall -= current.wall;
  199. m_times.user -= current.user;
  200. m_times.system -= current.system;
  201. }
  202. }
  203. // auto_cpu_timer ----------------------------------------------------------------//
  204. auto_cpu_timer::auto_cpu_timer(std::ostream& os, short places) // #5
  205. : m_places(places), m_os(&os), m_format(default_fmt)
  206. {
  207. start();
  208. }
  209. void auto_cpu_timer::report()
  210. {
  211. show_time(elapsed(), ostream(), format_string(), places());
  212. }
  213. auto_cpu_timer::~auto_cpu_timer()
  214. {
  215. if (!is_stopped())
  216. {
  217. stop(); // the sooner we stop(), the better
  218. try
  219. {
  220. report();
  221. }
  222. catch (...) // eat any exceptions
  223. {
  224. }
  225. }
  226. }
  227. } // namespace timer
  228. } // namespace boost