1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef PLATFORM_BASE_TRIVIAL_CLOCK_TRAITS_H_
6 #define PLATFORM_BASE_TRIVIAL_CLOCK_TRAITS_H_
7 
8 #include <chrono>
9 #include <ostream>
10 
11 namespace openscreen {
12 
13 // The Open Screen monotonic clock traits description, providing all the C++14
14 // requirements of a TrivialClock, for use with STL <chrono>.
15 class TrivialClockTraits {
16  public:
17   // TrivialClock named requirements: std::chrono templates can/may use these.
18   // NOTE: unless you are specifically integrating with the clock, you probably
19   // don't want to use these types, and instead should reference the std::chrono
20   // types directly.
21   using duration = std::chrono::microseconds;
22   using rep = duration::rep;
23   using period = duration::period;
24   using time_point = std::chrono::time_point<TrivialClockTraits, duration>;
25   static constexpr bool is_steady = true;
26 
27   // Helper method for named requirements.
28   template <typename D>
to_duration(D d)29   static constexpr duration to_duration(D d) {
30     return std::chrono::duration_cast<duration>(d);
31   }
32 
33   // Time point values from the clock use microsecond precision, as a reasonably
34   // high-resolution clock is required. The time source must tick forward at
35   // least 10000 times per second.
36   using kRequiredResolution = std::ratio<1, 10000>;
37 
38   // In <chrono>, a clock type is just some type properties plus a static now()
39   // function. So, there's nothing to instantiate here.
40   TrivialClockTraits() = delete;
41   ~TrivialClockTraits() = delete;
42 
43   // "Trivially copyable" is necessary for using the time types in
44   // std::atomic<>.
45   static_assert(std::is_trivially_copyable<duration>(),
46                 "duration is not trivially copyable");
47   static_assert(std::is_trivially_copyable<time_point>(),
48                 "time_point is not trivially copyable");
49 };
50 
51 // Convenience type definition, for injecting time sources into classes (e.g.,
52 // &Clock::now versus something else for testing).
53 using ClockNowFunctionPtr = TrivialClockTraits::time_point (*)();
54 
55 // Logging convenience for durations. Outputs a string of the form "123µs".
56 std::ostream& operator<<(std::ostream& os,
57                          const TrivialClockTraits::duration& d);
58 
59 // Logging convenience for time points. Outputs a string of the form
60 // "123µs-ticks".
61 std::ostream& operator<<(std::ostream& os,
62                          const TrivialClockTraits::time_point& tp);
63 
64 // Logging (and gtest pretty-printing) for several commonly-used chrono types.
65 std::ostream& operator<<(std::ostream& out, const std::chrono::hours&);
66 std::ostream& operator<<(std::ostream& out, const std::chrono::minutes&);
67 std::ostream& operator<<(std::ostream& out, const std::chrono::seconds&);
68 std::ostream& operator<<(std::ostream& out, const std::chrono::milliseconds&);
69 // Note: The ostream output operator for std::chrono::microseconds is handled by
70 // the one for TrivialClockTraits::duration above since they are the same type.
71 
72 }  // namespace openscreen
73 
74 #endif  // PLATFORM_BASE_TRIVIAL_CLOCK_TRAITS_H_
75