1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <chrono>
20 #include <string>
21 
22 #include <android-base/stringprintf.h>
23 #include <utils/Timers.h>
24 
25 namespace android {
26 namespace scheduler {
27 
28 // TODO(b/185535769): Pull Clock.h to libscheduler to reuse this.
29 using SchedulerClock = std::chrono::steady_clock;
30 static_assert(SchedulerClock::is_steady);
31 
32 } // namespace scheduler
33 
34 struct Duration;
35 
36 struct TimePoint : scheduler::SchedulerClock::time_point {
37     constexpr TimePoint() = default;
38     explicit constexpr TimePoint(const Duration&);
39 
40     // Implicit conversion from std::chrono counterpart.
TimePointTimePoint41     constexpr TimePoint(scheduler::SchedulerClock::time_point p)
42           : scheduler::SchedulerClock::time_point(p) {}
43 
44     static constexpr TimePoint fromNs(nsecs_t);
45 
nowTimePoint46     static TimePoint now() { return scheduler::SchedulerClock::now(); };
47 
48     nsecs_t ns() const;
49 };
50 
51 struct Duration : TimePoint::duration {
52     // Implicit conversion from std::chrono counterpart.
53     template <typename R, typename P>
DurationDuration54     constexpr Duration(std::chrono::duration<R, P> d) : TimePoint::duration(d) {}
55 
fromNsDuration56     static constexpr Duration fromNs(nsecs_t ns) { return {std::chrono::nanoseconds(ns)}; }
57 
nsDuration58     nsecs_t ns() const { return std::chrono::nanoseconds(*this).count(); }
59 };
60 
61 using Period = Duration;
62 
TimePoint(const Duration & d)63 constexpr TimePoint::TimePoint(const Duration& d) : scheduler::SchedulerClock::time_point(d) {}
64 
fromNs(nsecs_t ns)65 constexpr TimePoint TimePoint::fromNs(nsecs_t ns) {
66     return TimePoint(Duration::fromNs(ns));
67 }
68 
ns()69 inline nsecs_t TimePoint::ns() const {
70     return Duration(time_since_epoch()).ns();
71 }
72 
73 // Shorthand to convert the tick count of a Duration to Period and Rep. For example:
74 //
75 //     const auto i = ticks<std::ratio<1>>(d);      // Integer seconds.
76 //     const auto f = ticks<std::milli, float>(d);  // Floating-point milliseconds.
77 //
78 template <typename Period, typename Rep = Duration::rep>
ticks(Duration d)79 constexpr Rep ticks(Duration d) {
80     using D = std::chrono::duration<Rep, Period>;
81     return std::chrono::duration_cast<D>(d).count();
82 }
83 
to_string(Duration d)84 inline std::string to_string(Duration d) {
85     return base::StringPrintf("%.3f ms", ticks<std::milli, float>(d));
86 }
87 
88 } // namespace android
89