1 //===- llvm/Support/Chrono.h - Utilities for Timing Manipulation-*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_SUPPORT_CHRONO_H
10 #define LLVM_SUPPORT_CHRONO_H
12 #include "llvm/Support/Compiler.h"
13 #include "llvm/Support/FormatProviders.h"
24 /// A time point on the system clock. This is provided for two reasons:
25 /// - to insulate us agains subtle differences in behavoir to differences in
26 /// system clock precision (which is implementation-defined and differs between
28 /// - to shorten the type name
29 /// The default precision is nanoseconds. If need a specific precision specify
30 /// it explicitly. If unsure, use the default. If you need a time point on a
31 /// clock other than the system_clock, use std::chrono directly.
32 template <typename D
= std::chrono::nanoseconds
>
33 using TimePoint
= std::chrono::time_point
<std::chrono::system_clock
, D
>;
35 /// Convert a TimePoint to std::time_t
36 inline std::time_t toTimeT(TimePoint
<> TP
) {
37 using namespace std::chrono
;
38 return system_clock::to_time_t(
39 time_point_cast
<system_clock::time_point::duration
>(TP
));
42 /// Convert a std::time_t to a TimePoint
43 inline TimePoint
<std::chrono::seconds
>
44 toTimePoint(std::time_t T
) {
45 using namespace std::chrono
;
46 return time_point_cast
<seconds
>(system_clock::from_time_t(T
));
49 /// Convert a std::time_t + nanoseconds to a TimePoint
51 toTimePoint(std::time_t T
, uint32_t nsec
) {
52 using namespace std::chrono
;
53 return time_point_cast
<nanoseconds
>(system_clock::from_time_t(T
))
59 raw_ostream
&operator<<(raw_ostream
&OS
, sys::TimePoint
<> TP
);
61 /// Format provider for TimePoint<>
63 /// The options string is a strftime format string, with extensions:
64 /// - %L is millis: 000-999
65 /// - %f is micros: 000000-999999
66 /// - %N is nanos: 000000000 - 999999999
68 /// If no options are given, the default format is "%Y-%m-%d %H:%M:%S.%N".
70 struct format_provider
<sys::TimePoint
<>> {
71 static void format(const sys::TimePoint
<> &TP
, llvm::raw_ostream
&OS
,
75 /// Implementation of format_provider<T> for duration types.
77 /// The options string of a duration type has the grammar:
79 /// duration_options ::= [unit][show_unit [number_options]]
80 /// unit ::= `h`|`m`|`s`|`ms|`us`|`ns`
81 /// show_unit ::= `+` | `-`
82 /// number_options ::= options string for a integral or floating point type
85 /// =================================
86 /// | options | Input | Output |
87 /// =================================
89 /// | "ms" | 1s | 1000 ms |
90 /// | "ms-" | 1s | 1000 |
91 /// | "ms-n" | 1s | 1,000 |
92 /// | "" | 1.0s | 1.00 s |
93 /// =================================
95 /// If the unit of the duration type is not one of the units specified above,
96 /// it is still possible to format it, provided you explicitly request a
97 /// display unit or you request that the unit is not displayed.
100 template <typename Period
> struct unit
{ static const char value
[]; };
101 template <typename Period
> const char unit
<Period
>::value
[] = "";
103 template <> struct unit
<std::ratio
<3600>> { static const char value
[]; };
104 template <> struct unit
<std::ratio
<60>> { static const char value
[]; };
105 template <> struct unit
<std::ratio
<1>> { static const char value
[]; };
106 template <> struct unit
<std::milli
> { static const char value
[]; };
107 template <> struct unit
<std::micro
> { static const char value
[]; };
108 template <> struct unit
<std::nano
> { static const char value
[]; };
109 } // namespace detail
111 template <typename Rep
, typename Period
>
112 struct format_provider
<std::chrono::duration
<Rep
, Period
>> {
114 typedef std::chrono::duration
<Rep
, Period
> Dur
;
115 typedef typename
std::conditional
<
116 std::chrono::treat_as_floating_point
<Rep
>::value
, double, intmax_t>::type
119 template <typename AsPeriod
> static InternalRep
getAs(const Dur
&D
) {
120 using namespace std::chrono
;
121 return duration_cast
<duration
<InternalRep
, AsPeriod
>>(D
).count();
124 static std::pair
<InternalRep
, StringRef
> consumeUnit(StringRef
&Style
,
126 using namespace std::chrono
;
127 if (Style
.consume_front("ns"))
128 return {getAs
<std::nano
>(D
), "ns"};
129 if (Style
.consume_front("us"))
130 return {getAs
<std::micro
>(D
), "us"};
131 if (Style
.consume_front("ms"))
132 return {getAs
<std::milli
>(D
), "ms"};
133 if (Style
.consume_front("s"))
134 return {getAs
<std::ratio
<1>>(D
), "s"};
135 if (Style
.consume_front("m"))
136 return {getAs
<std::ratio
<60>>(D
), "m"};
137 if (Style
.consume_front("h"))
138 return {getAs
<std::ratio
<3600>>(D
), "h"};
139 return {D
.count(), detail::unit
<Period
>::value
};
142 static bool consumeShowUnit(StringRef
&Style
) {
145 if (Style
.consume_front("-"))
147 if (Style
.consume_front("+"))
149 assert(0 && "Unrecognised duration format");
154 static void format(const Dur
&D
, llvm::raw_ostream
&Stream
, StringRef Style
) {
157 std::tie(count
, unit
) = consumeUnit(Style
, D
);
158 bool show_unit
= consumeShowUnit(Style
);
160 format_provider
<InternalRep
>::format(count
, Stream
, Style
);
163 assert(!unit
.empty());
164 Stream
<< " " << unit
;
171 #endif // LLVM_SUPPORT_CHRONO_H