Chrono.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/Support/Chrono.h - Utilities for Timing Manipulation-*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_SUPPORT_CHRONO_H
  14. #define LLVM_SUPPORT_CHRONO_H
  15. #include "llvm/Support/Compiler.h"
  16. #include "llvm/Support/FormatProviders.h"
  17. #include <chrono>
  18. #include <ctime>
  19. #include <ratio>
  20. namespace llvm {
  21. class raw_ostream;
  22. namespace sys {
  23. /// A time point on the system clock. This is provided for two reasons:
  24. /// - to insulate us against subtle differences in behavior to differences in
  25. /// system clock precision (which is implementation-defined and differs
  26. /// between platforms).
  27. /// - to shorten the type name
  28. /// The default precision is nanoseconds. If you need a specific precision
  29. /// specify it explicitly. If unsure, use the default. If you need a time point
  30. /// on a clock other than the system_clock, use std::chrono directly.
  31. template <typename D = std::chrono::nanoseconds>
  32. using TimePoint = std::chrono::time_point<std::chrono::system_clock, D>;
  33. /// Convert a TimePoint to std::time_t
  34. inline std::time_t toTimeT(TimePoint<> TP) {
  35. using namespace std::chrono;
  36. return system_clock::to_time_t(
  37. time_point_cast<system_clock::time_point::duration>(TP));
  38. }
  39. /// Convert a std::time_t to a TimePoint
  40. inline TimePoint<std::chrono::seconds>
  41. toTimePoint(std::time_t T) {
  42. using namespace std::chrono;
  43. return time_point_cast<seconds>(system_clock::from_time_t(T));
  44. }
  45. /// Convert a std::time_t + nanoseconds to a TimePoint
  46. inline TimePoint<>
  47. toTimePoint(std::time_t T, uint32_t nsec) {
  48. using namespace std::chrono;
  49. return time_point_cast<nanoseconds>(system_clock::from_time_t(T))
  50. + nanoseconds(nsec);
  51. }
  52. } // namespace sys
  53. raw_ostream &operator<<(raw_ostream &OS, sys::TimePoint<> TP);
  54. /// Format provider for TimePoint<>
  55. ///
  56. /// The options string is a strftime format string, with extensions:
  57. /// - %L is millis: 000-999
  58. /// - %f is micros: 000000-999999
  59. /// - %N is nanos: 000000000 - 999999999
  60. ///
  61. /// If no options are given, the default format is "%Y-%m-%d %H:%M:%S.%N".
  62. template <>
  63. struct format_provider<sys::TimePoint<>> {
  64. static void format(const sys::TimePoint<> &TP, llvm::raw_ostream &OS,
  65. StringRef Style);
  66. };
  67. namespace detail {
  68. template <typename Period> struct unit { static const char value[]; };
  69. template <typename Period> const char unit<Period>::value[] = "";
  70. template <> struct unit<std::ratio<3600>> { static const char value[]; };
  71. template <> struct unit<std::ratio<60>> { static const char value[]; };
  72. template <> struct unit<std::ratio<1>> { static const char value[]; };
  73. template <> struct unit<std::milli> { static const char value[]; };
  74. template <> struct unit<std::micro> { static const char value[]; };
  75. template <> struct unit<std::nano> { static const char value[]; };
  76. } // namespace detail
  77. /// Implementation of format_provider<T> for duration types.
  78. ///
  79. /// The options string of a duration type has the grammar:
  80. ///
  81. /// duration_options ::= [unit][show_unit [number_options]]
  82. /// unit ::= `h`|`m`|`s`|`ms|`us`|`ns`
  83. /// show_unit ::= `+` | `-`
  84. /// number_options ::= options string for a integral or floating point type
  85. ///
  86. /// Examples
  87. /// =================================
  88. /// | options | Input | Output |
  89. /// =================================
  90. /// | "" | 1s | 1 s |
  91. /// | "ms" | 1s | 1000 ms |
  92. /// | "ms-" | 1s | 1000 |
  93. /// | "ms-n" | 1s | 1,000 |
  94. /// | "" | 1.0s | 1.00 s |
  95. /// =================================
  96. ///
  97. /// If the unit of the duration type is not one of the units specified above,
  98. /// it is still possible to format it, provided you explicitly request a
  99. /// display unit or you request that the unit is not displayed.
  100. template <typename Rep, typename Period>
  101. struct format_provider<std::chrono::duration<Rep, Period>> {
  102. private:
  103. typedef std::chrono::duration<Rep, Period> Dur;
  104. typedef std::conditional_t<std::chrono::treat_as_floating_point<Rep>::value,
  105. double, intmax_t>
  106. InternalRep;
  107. template <typename AsPeriod> static InternalRep getAs(const Dur &D) {
  108. using namespace std::chrono;
  109. return duration_cast<duration<InternalRep, AsPeriod>>(D).count();
  110. }
  111. static std::pair<InternalRep, StringRef> consumeUnit(StringRef &Style,
  112. const Dur &D) {
  113. using namespace std::chrono;
  114. if (Style.consume_front("ns"))
  115. return {getAs<std::nano>(D), "ns"};
  116. if (Style.consume_front("us"))
  117. return {getAs<std::micro>(D), "us"};
  118. if (Style.consume_front("ms"))
  119. return {getAs<std::milli>(D), "ms"};
  120. if (Style.consume_front("s"))
  121. return {getAs<std::ratio<1>>(D), "s"};
  122. if (Style.consume_front("m"))
  123. return {getAs<std::ratio<60>>(D), "m"};
  124. if (Style.consume_front("h"))
  125. return {getAs<std::ratio<3600>>(D), "h"};
  126. return {D.count(), detail::unit<Period>::value};
  127. }
  128. static bool consumeShowUnit(StringRef &Style) {
  129. if (Style.empty())
  130. return true;
  131. if (Style.consume_front("-"))
  132. return false;
  133. if (Style.consume_front("+"))
  134. return true;
  135. assert(0 && "Unrecognised duration format");
  136. return true;
  137. }
  138. public:
  139. static void format(const Dur &D, llvm::raw_ostream &Stream, StringRef Style) {
  140. InternalRep count;
  141. StringRef unit;
  142. std::tie(count, unit) = consumeUnit(Style, D);
  143. bool show_unit = consumeShowUnit(Style);
  144. format_provider<InternalRep>::format(count, Stream, Style);
  145. if (show_unit) {
  146. assert(!unit.empty());
  147. Stream << " " << unit;
  148. }
  149. }
  150. };
  151. } // namespace llvm
  152. #endif // LLVM_SUPPORT_CHRONO_H
  153. #ifdef __GNUC__
  154. #pragma GCC diagnostic pop
  155. #endif