Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:28

0001 //===- llvm/Support/Chrono.h - Utilities for Timing Manipulation-*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_SUPPORT_CHRONO_H
0010 #define LLVM_SUPPORT_CHRONO_H
0011 
0012 #include "llvm/Support/Compiler.h"
0013 #include "llvm/Support/FormatProviders.h"
0014 
0015 #include <chrono>
0016 #include <ctime>
0017 #include <ratio>
0018 
0019 namespace llvm {
0020 
0021 class raw_ostream;
0022 
0023 namespace sys {
0024 
0025 /// A time point on the system clock. This is provided for two reasons:
0026 /// - to insulate us against subtle differences in behavior to differences in
0027 ///   system clock precision (which is implementation-defined and differs
0028 ///   between platforms).
0029 /// - to shorten the type name
0030 /// The default precision is nanoseconds. If you need a specific precision
0031 /// specify it explicitly. If unsure, use the default. If you need a time point
0032 /// on a clock other than the system_clock, use std::chrono directly.
0033 template <typename D = std::chrono::nanoseconds>
0034 using TimePoint = std::chrono::time_point<std::chrono::system_clock, D>;
0035 
0036 // utc_clock and utc_time are only available since C++20. Add enough code to
0037 // support formatting date/time in UTC.
0038 class UtcClock : public std::chrono::system_clock {};
0039 
0040 template <typename D = std::chrono::nanoseconds>
0041 using UtcTime = std::chrono::time_point<UtcClock, D>;
0042 
0043 /// Convert a std::time_t to a UtcTime
0044 inline UtcTime<std::chrono::seconds> toUtcTime(std::time_t T) {
0045   using namespace std::chrono;
0046   return UtcTime<seconds>(seconds(T));
0047 }
0048 
0049 /// Convert a TimePoint to std::time_t
0050 inline std::time_t toTimeT(TimePoint<> TP) {
0051   using namespace std::chrono;
0052   return system_clock::to_time_t(
0053       time_point_cast<system_clock::time_point::duration>(TP));
0054 }
0055 
0056 /// Convert a UtcTime to std::time_t
0057 inline std::time_t toTimeT(UtcTime<> TP) {
0058   using namespace std::chrono;
0059   return system_clock::to_time_t(time_point<system_clock, seconds>(
0060       duration_cast<seconds>(TP.time_since_epoch())));
0061 }
0062 
0063 /// Convert a std::time_t to a TimePoint
0064 inline TimePoint<std::chrono::seconds>
0065 toTimePoint(std::time_t T) {
0066   using namespace std::chrono;
0067   return time_point_cast<seconds>(system_clock::from_time_t(T));
0068 }
0069 
0070 /// Convert a std::time_t + nanoseconds to a TimePoint
0071 inline TimePoint<>
0072 toTimePoint(std::time_t T, uint32_t nsec) {
0073   using namespace std::chrono;
0074   return time_point_cast<nanoseconds>(system_clock::from_time_t(T))
0075     + nanoseconds(nsec);
0076 }
0077 
0078 } // namespace sys
0079 
0080 raw_ostream &operator<<(raw_ostream &OS, sys::TimePoint<> TP);
0081 raw_ostream &operator<<(raw_ostream &OS, sys::UtcTime<> TP);
0082 
0083 /// Format provider for TimePoint<>
0084 ///
0085 /// The options string is a strftime format string, with extensions:
0086 ///   - %L is millis: 000-999
0087 ///   - %f is micros: 000000-999999
0088 ///   - %N is nanos: 000000000 - 999999999
0089 ///
0090 /// If no options are given, the default format is "%Y-%m-%d %H:%M:%S.%N".
0091 template <>
0092 struct format_provider<sys::TimePoint<>> {
0093   static void format(const sys::TimePoint<> &TP, llvm::raw_ostream &OS,
0094                      StringRef Style);
0095 };
0096 
0097 template <> struct format_provider<sys::UtcTime<std::chrono::seconds>> {
0098   static void format(const sys::UtcTime<std::chrono::seconds> &TP,
0099                      llvm::raw_ostream &OS, StringRef Style);
0100 };
0101 
0102 namespace detail {
0103 template <typename Period> struct unit { static const char value[]; };
0104 template <typename Period> const char unit<Period>::value[] = "";
0105 
0106 template <> struct unit<std::ratio<3600>> { static const char value[]; };
0107 template <> struct unit<std::ratio<60>> { static const char value[]; };
0108 template <> struct unit<std::ratio<1>> { static const char value[]; };
0109 template <> struct unit<std::milli> { static const char value[]; };
0110 template <> struct unit<std::micro> { static const char value[]; };
0111 template <> struct unit<std::nano> { static const char value[]; };
0112 } // namespace detail
0113 
0114 /// Implementation of format_provider<T> for duration types.
0115 ///
0116 /// The options string of a duration type has the grammar:
0117 ///
0118 ///   duration_options  ::= [unit][show_unit [number_options]]
0119 ///   unit              ::= `h`|`m`|`s`|`ms|`us`|`ns`
0120 ///   show_unit         ::= `+` | `-`
0121 ///   number_options    ::= options string for a integral or floating point type
0122 ///
0123 ///   Examples
0124 ///   =================================
0125 ///   |  options  | Input | Output    |
0126 ///   =================================
0127 ///   | ""        | 1s    | 1 s       |
0128 ///   | "ms"      | 1s    | 1000 ms   |
0129 ///   | "ms-"     | 1s    | 1000      |
0130 ///   | "ms-n"    | 1s    | 1,000     |
0131 ///   | ""        | 1.0s  | 1.00 s    |
0132 ///   =================================
0133 ///
0134 ///  If the unit of the duration type is not one of the units specified above,
0135 ///  it is still possible to format it, provided you explicitly request a
0136 ///  display unit or you request that the unit is not displayed.
0137 
0138 template <typename Rep, typename Period>
0139 struct format_provider<std::chrono::duration<Rep, Period>> {
0140 private:
0141   typedef std::chrono::duration<Rep, Period> Dur;
0142   typedef std::conditional_t<std::chrono::treat_as_floating_point<Rep>::value,
0143                              double, intmax_t>
0144       InternalRep;
0145 
0146   template <typename AsPeriod> static InternalRep getAs(const Dur &D) {
0147     using namespace std::chrono;
0148     return duration_cast<duration<InternalRep, AsPeriod>>(D).count();
0149   }
0150 
0151   static std::pair<InternalRep, StringRef> consumeUnit(StringRef &Style,
0152                                                         const Dur &D) {
0153     using namespace std::chrono;
0154     if (Style.consume_front("ns"))
0155       return {getAs<std::nano>(D), "ns"};
0156     if (Style.consume_front("us"))
0157       return {getAs<std::micro>(D), "us"};
0158     if (Style.consume_front("ms"))
0159       return {getAs<std::milli>(D), "ms"};
0160     if (Style.consume_front("s"))
0161       return {getAs<std::ratio<1>>(D), "s"};
0162     if (Style.consume_front("m"))
0163       return {getAs<std::ratio<60>>(D), "m"};
0164     if (Style.consume_front("h"))
0165       return {getAs<std::ratio<3600>>(D), "h"};
0166     return {D.count(), detail::unit<Period>::value};
0167   }
0168 
0169   static bool consumeShowUnit(StringRef &Style) {
0170     if (Style.empty())
0171       return true;
0172     if (Style.consume_front("-"))
0173       return false;
0174     if (Style.consume_front("+"))
0175       return true;
0176     assert(0 && "Unrecognised duration format");
0177     return true;
0178   }
0179 
0180 public:
0181   static void format(const Dur &D, llvm::raw_ostream &Stream, StringRef Style) {
0182     InternalRep count;
0183     StringRef unit;
0184     std::tie(count, unit) = consumeUnit(Style, D);
0185     bool show_unit = consumeShowUnit(Style);
0186 
0187     format_provider<InternalRep>::format(count, Stream, Style);
0188 
0189     if (show_unit) {
0190       assert(!unit.empty());
0191       Stream << " " << unit;
0192     }
0193   }
0194 };
0195 
0196 } // namespace llvm
0197 
0198 #endif // LLVM_SUPPORT_CHRONO_H