chrono.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. //===------------------------- chrono.cpp ---------------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is dual licensed under the MIT and the University of Illinois Open
  6. // Source Licenses. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "__config"
  10. #if !defined(_LIBCPP_SGX_CONFIG)
  11. #include "chrono"
  12. #include "cerrno" // errno
  13. #include "system_error" // __throw_system_error
  14. #include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME
  15. #if !defined(CLOCK_REALTIME)
  16. #include <sys/time.h> // for gettimeofday and timeval
  17. #endif
  18. #if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) && !defined(CLOCK_MONOTONIC)
  19. #if __APPLE__
  20. #include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
  21. #else
  22. #error "Monotonic clock not implemented"
  23. #endif
  24. #endif
  25. _LIBCPP_BEGIN_NAMESPACE_STD
  26. namespace chrono
  27. {
  28. // system_clock
  29. const bool system_clock::is_steady;
  30. system_clock::time_point
  31. system_clock::now() _NOEXCEPT
  32. {
  33. #ifdef CLOCK_REALTIME
  34. struct timespec tp;
  35. if (0 != clock_gettime(CLOCK_REALTIME, &tp))
  36. __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
  37. return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000));
  38. #else // !CLOCK_REALTIME
  39. timeval tv;
  40. gettimeofday(&tv, 0);
  41. return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
  42. #endif // CLOCK_REALTIME
  43. }
  44. time_t
  45. system_clock::to_time_t(const time_point& t) _NOEXCEPT
  46. {
  47. return time_t(duration_cast<seconds>(t.time_since_epoch()).count());
  48. }
  49. system_clock::time_point
  50. system_clock::from_time_t(time_t t) _NOEXCEPT
  51. {
  52. return system_clock::time_point(seconds(t));
  53. }
  54. #ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK
  55. // steady_clock
  56. //
  57. // Warning: If this is not truly steady, then it is non-conforming. It is
  58. // better for it to not exist and have the rest of libc++ use system_clock
  59. // instead.
  60. const bool steady_clock::is_steady;
  61. #ifdef CLOCK_MONOTONIC
  62. steady_clock::time_point
  63. steady_clock::now() _NOEXCEPT
  64. {
  65. struct timespec tp;
  66. if (0 != clock_gettime(CLOCK_MONOTONIC, &tp))
  67. __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed");
  68. return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
  69. }
  70. #elif defined(__APPLE__)
  71. // mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
  72. // nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom
  73. // are run time constants supplied by the OS. This clock has no relationship
  74. // to the Gregorian calendar. It's main use is as a high resolution timer.
  75. // MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize
  76. // for that case as an optimization.
  77. #pragma GCC visibility push(hidden)
  78. static
  79. steady_clock::rep
  80. steady_simplified()
  81. {
  82. return static_cast<steady_clock::rep>(mach_absolute_time());
  83. }
  84. static
  85. double
  86. compute_steady_factor()
  87. {
  88. mach_timebase_info_data_t MachInfo;
  89. mach_timebase_info(&MachInfo);
  90. return static_cast<double>(MachInfo.numer) / MachInfo.denom;
  91. }
  92. static
  93. steady_clock::rep
  94. steady_full()
  95. {
  96. static const double factor = compute_steady_factor();
  97. return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
  98. }
  99. typedef steady_clock::rep (*FP)();
  100. static
  101. FP
  102. init_steady_clock()
  103. {
  104. mach_timebase_info_data_t MachInfo;
  105. mach_timebase_info(&MachInfo);
  106. if (MachInfo.numer == MachInfo.denom)
  107. return &steady_simplified;
  108. return &steady_full;
  109. }
  110. #pragma GCC visibility pop
  111. steady_clock::time_point
  112. steady_clock::now() _NOEXCEPT
  113. {
  114. static FP fp = init_steady_clock();
  115. return time_point(duration(fp()));
  116. }
  117. #else
  118. #error "Monotonic clock not implemented"
  119. #endif
  120. #endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK
  121. }
  122. _LIBCPP_END_NAMESPACE_STD
  123. #endif // !defined(_LIBCPP_SGX_CONFIG)