1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef GRPC_SRC_CORE_LIB_GPRPP_TIME_H
16 #define GRPC_SRC_CORE_LIB_GPRPP_TIME_H
17
18 #include <grpc/support/port_platform.h>
19
20 #include <stdint.h>
21
22 #include <limits>
23 #include <ostream>
24 #include <string>
25
26 #include "absl/types/optional.h"
27
28 #include <grpc/event_engine/event_engine.h>
29 #include <grpc/support/time.h>
30
31 #include "src/core/lib/gpr/time_precise.h"
32 #include "src/core/lib/gpr/useful.h"
33
34 #define GRPC_LOG_EVERY_N_SEC(n, severity, format, ...) \
35 do { \
36 static std::atomic<uint64_t> prev{0}; \
37 uint64_t now = grpc_core::Timestamp::FromTimespecRoundDown( \
38 gpr_now(GPR_CLOCK_MONOTONIC)) \
39 .milliseconds_after_process_epoch(); \
40 uint64_t prev_tsamp = prev.exchange(now); \
41 if (prev_tsamp == 0 || now - prev_tsamp > (n)*1000) { \
42 gpr_log(severity, format, __VA_ARGS__); \
43 } \
44 } while (0)
45
46 namespace grpc_core {
47
48 namespace time_detail {
49
MillisAdd(int64_t a,int64_t b)50 inline int64_t MillisAdd(int64_t a, int64_t b) {
51 if (a == std::numeric_limits<int64_t>::max() ||
52 b == std::numeric_limits<int64_t>::max()) {
53 return std::numeric_limits<int64_t>::max();
54 }
55 if (a == std::numeric_limits<int64_t>::min() ||
56 b == std::numeric_limits<int64_t>::min()) {
57 return std::numeric_limits<int64_t>::min();
58 }
59 return SaturatingAdd(a, b);
60 }
61
MillisMul(int64_t millis,int64_t mul)62 constexpr inline int64_t MillisMul(int64_t millis, int64_t mul) {
63 return millis >= std::numeric_limits<int64_t>::max() / mul
64 ? std::numeric_limits<int64_t>::max()
65 : millis <= std::numeric_limits<int64_t>::min() / mul
66 ? std::numeric_limits<int64_t>::min()
67 : millis * mul;
68 }
69
70 } // namespace time_detail
71
72 class Duration;
73
74 // Timestamp represents a discrete point in time.
75 class Timestamp {
76 public:
77 // Base interface for time providers.
78 class Source {
79 public:
80 // Return the current time.
81 virtual Timestamp Now() = 0;
InvalidateCache()82 virtual void InvalidateCache() {}
83
84 protected:
85 // We don't delete through this interface, so non-virtual dtor is fine.
86 ~Source() = default;
87 };
88
89 class ScopedSource : public Source {
90 public:
ScopedSource()91 ScopedSource() : previous_(thread_local_time_source_) {
92 thread_local_time_source_ = this;
93 }
94 ScopedSource(const ScopedSource&) = delete;
95 ScopedSource& operator=(const ScopedSource&) = delete;
InvalidateCache()96 void InvalidateCache() override { previous_->InvalidateCache(); }
97
98 protected:
~ScopedSource()99 ~ScopedSource() { thread_local_time_source_ = previous_; }
previous()100 Source* previous() const { return previous_; }
101
102 private:
103 Source* const previous_;
104 };
105
106 constexpr Timestamp() = default;
107 // Constructs a Timestamp from a gpr_timespec.
108 static Timestamp FromTimespecRoundDown(gpr_timespec t);
109 static Timestamp FromTimespecRoundUp(gpr_timespec t);
110
111 // Construct a Timestamp from a gpr_cycle_counter.
112 static Timestamp FromCycleCounterRoundUp(gpr_cycle_counter c);
113 static Timestamp FromCycleCounterRoundDown(gpr_cycle_counter c);
114
Now()115 static Timestamp Now() { return thread_local_time_source_->Now(); }
116
FromMillisecondsAfterProcessEpoch(int64_t millis)117 static constexpr Timestamp FromMillisecondsAfterProcessEpoch(int64_t millis) {
118 return Timestamp(millis);
119 }
120
ProcessEpoch()121 static constexpr Timestamp ProcessEpoch() { return Timestamp(0); }
122
InfFuture()123 static constexpr Timestamp InfFuture() {
124 return Timestamp(std::numeric_limits<int64_t>::max());
125 }
126
InfPast()127 static constexpr Timestamp InfPast() {
128 return Timestamp(std::numeric_limits<int64_t>::min());
129 }
130
131 constexpr bool operator==(Timestamp other) const {
132 return millis_ == other.millis_;
133 }
134 constexpr bool operator!=(Timestamp other) const {
135 return millis_ != other.millis_;
136 }
137 constexpr bool operator<(Timestamp other) const {
138 return millis_ < other.millis_;
139 }
140 constexpr bool operator<=(Timestamp other) const {
141 return millis_ <= other.millis_;
142 }
143 constexpr bool operator>(Timestamp other) const {
144 return millis_ > other.millis_;
145 }
146 constexpr bool operator>=(Timestamp other) const {
147 return millis_ >= other.millis_;
148 }
149 Timestamp& operator+=(Duration duration);
150
is_process_epoch()151 bool is_process_epoch() const { return millis_ == 0; }
152
milliseconds_after_process_epoch()153 uint64_t milliseconds_after_process_epoch() const { return millis_; }
154
155 gpr_timespec as_timespec(gpr_clock_type type) const;
156
157 std::string ToString() const;
158
159 private:
Timestamp(int64_t millis)160 explicit constexpr Timestamp(int64_t millis) : millis_(millis) {}
161
162 int64_t millis_ = 0;
163 static thread_local Timestamp::Source* thread_local_time_source_;
164 };
165
166 class ScopedTimeCache final : public Timestamp::ScopedSource {
167 public:
168 Timestamp Now() override;
169
InvalidateCache()170 void InvalidateCache() override {
171 cached_time_ = absl::nullopt;
172 Timestamp::ScopedSource::InvalidateCache();
173 }
TestOnlySetNow(Timestamp now)174 void TestOnlySetNow(Timestamp now) { cached_time_ = now; }
175
176 private:
177 absl::optional<Timestamp> cached_time_;
178 };
179
180 // Duration represents a span of time.
181 class Duration {
182 public:
Duration()183 constexpr Duration() noexcept : millis_(0) {}
184
185 static Duration FromTimespec(gpr_timespec t);
186 static Duration FromSecondsAndNanoseconds(int64_t seconds, int32_t nanos);
187 static Duration FromSecondsAsDouble(double seconds);
188
Zero()189 static constexpr Duration Zero() { return Duration(0); }
190
191 // Smallest representatable positive duration.
Epsilon()192 static constexpr Duration Epsilon() { return Duration(1); }
193
NegativeInfinity()194 static constexpr Duration NegativeInfinity() {
195 return Duration(std::numeric_limits<int64_t>::min());
196 }
197
Infinity()198 static constexpr Duration Infinity() {
199 return Duration(std::numeric_limits<int64_t>::max());
200 }
201
Hours(int64_t hours)202 static constexpr Duration Hours(int64_t hours) {
203 return Minutes(time_detail::MillisMul(hours, 60));
204 }
205
Minutes(int64_t minutes)206 static constexpr Duration Minutes(int64_t minutes) {
207 return Seconds(time_detail::MillisMul(minutes, 60));
208 }
209
Seconds(int64_t seconds)210 static constexpr Duration Seconds(int64_t seconds) {
211 return Milliseconds(time_detail::MillisMul(seconds, GPR_MS_PER_SEC));
212 }
213
Milliseconds(int64_t millis)214 static constexpr Duration Milliseconds(int64_t millis) {
215 return Duration(millis);
216 }
217
MicrosecondsRoundDown(int64_t micros)218 static constexpr Duration MicrosecondsRoundDown(int64_t micros) {
219 return Duration(micros / GPR_US_PER_MS);
220 }
221
NanosecondsRoundDown(int64_t nanos)222 static constexpr Duration NanosecondsRoundDown(int64_t nanos) {
223 return Duration(nanos / GPR_NS_PER_MS);
224 }
225
MicrosecondsRoundUp(int64_t micros)226 static constexpr Duration MicrosecondsRoundUp(int64_t micros) {
227 return Duration(micros / GPR_US_PER_MS + (micros % GPR_US_PER_MS != 0));
228 }
229
NanosecondsRoundUp(int64_t nanos)230 static constexpr Duration NanosecondsRoundUp(int64_t nanos) {
231 return Duration(nanos / GPR_NS_PER_MS + (nanos % GPR_NS_PER_MS != 0));
232 }
233
234 constexpr bool operator==(Duration other) const {
235 return millis_ == other.millis_;
236 }
237 constexpr bool operator!=(Duration other) const {
238 return millis_ != other.millis_;
239 }
240 constexpr bool operator<(Duration other) const {
241 return millis_ < other.millis_;
242 }
243 constexpr bool operator<=(Duration other) const {
244 return millis_ <= other.millis_;
245 }
246 constexpr bool operator>(Duration other) const {
247 return millis_ > other.millis_;
248 }
249 constexpr bool operator>=(Duration other) const {
250 return millis_ >= other.millis_;
251 }
252 Duration& operator/=(int64_t divisor) {
253 if (millis_ == std::numeric_limits<int64_t>::max()) {
254 *this = divisor < 0 ? NegativeInfinity() : Infinity();
255 } else if (millis_ == std::numeric_limits<int64_t>::min()) {
256 *this = divisor < 0 ? Infinity() : NegativeInfinity();
257 } else {
258 millis_ /= divisor;
259 }
260 return *this;
261 }
262 Duration& operator*=(double multiplier);
263 Duration& operator+=(Duration other) {
264 millis_ += other.millis_;
265 return *this;
266 }
267
millis()268 constexpr int64_t millis() const { return millis_; }
seconds()269 double seconds() const { return static_cast<double>(millis_) / 1000.0; }
270
271 // NOLINTNEXTLINE: google-explicit-constructor
272 operator grpc_event_engine::experimental::EventEngine::Duration() const;
273
274 gpr_timespec as_timespec() const;
275
276 std::string ToString() const;
277
278 // Returns the duration in the JSON form corresponding to a
279 // google.protobuf.Duration proto, as defined here:
280 // https://developers.google.com/protocol-buffers/docs/proto3#json
281 std::string ToJsonString() const;
282
283 private:
Duration(int64_t millis)284 explicit constexpr Duration(int64_t millis) : millis_(millis) {}
285
286 int64_t millis_;
287 };
288
289 inline Duration operator+(Duration lhs, Duration rhs) {
290 return Duration::Milliseconds(
291 time_detail::MillisAdd(lhs.millis(), rhs.millis()));
292 }
293
294 inline Duration operator-(Duration lhs, Duration rhs) {
295 return Duration::Milliseconds(
296 time_detail::MillisAdd(lhs.millis(), -rhs.millis()));
297 }
298
299 inline Timestamp operator+(Timestamp lhs, Duration rhs) {
300 return Timestamp::FromMillisecondsAfterProcessEpoch(time_detail::MillisAdd(
301 lhs.milliseconds_after_process_epoch(), rhs.millis()));
302 }
303
304 inline Timestamp operator-(Timestamp lhs, Duration rhs) {
305 return Timestamp::FromMillisecondsAfterProcessEpoch(time_detail::MillisAdd(
306 lhs.milliseconds_after_process_epoch(), -rhs.millis()));
307 }
308
309 inline Timestamp operator+(Duration lhs, Timestamp rhs) { return rhs + lhs; }
310
311 inline Duration operator-(Timestamp lhs, Timestamp rhs) {
312 return Duration::Milliseconds(
313 time_detail::MillisAdd(lhs.milliseconds_after_process_epoch(),
314 -rhs.milliseconds_after_process_epoch()));
315 }
316
317 inline Duration operator*(Duration lhs, double rhs) {
318 if (lhs == Duration::Infinity()) {
319 return rhs < 0 ? Duration::NegativeInfinity() : Duration::Infinity();
320 }
321 if (lhs == Duration::NegativeInfinity()) {
322 return rhs < 0 ? Duration::Infinity() : Duration::NegativeInfinity();
323 }
324 return Duration::FromSecondsAsDouble(lhs.millis() * rhs / 1000.0);
325 }
326
327 inline Duration operator*(double lhs, Duration rhs) { return rhs * lhs; }
328
329 inline Duration operator/(Duration lhs, int64_t rhs) {
330 lhs /= rhs;
331 return lhs;
332 }
333
FromSecondsAndNanoseconds(int64_t seconds,int32_t nanos)334 inline Duration Duration::FromSecondsAndNanoseconds(int64_t seconds,
335 int32_t nanos) {
336 return Seconds(seconds) + NanosecondsRoundDown(nanos);
337 }
338
FromSecondsAsDouble(double seconds)339 inline Duration Duration::FromSecondsAsDouble(double seconds) {
340 double millis = seconds * 1000.0;
341 if (millis >= static_cast<double>(std::numeric_limits<int64_t>::max())) {
342 return Infinity();
343 }
344 if (millis <= static_cast<double>(std::numeric_limits<int64_t>::min())) {
345 return NegativeInfinity();
346 }
347 return Milliseconds(static_cast<int64_t>(millis));
348 }
349
350 inline Duration& Duration::operator*=(double multiplier) {
351 *this = *this * multiplier;
352 return *this;
353 }
354
355 inline Timestamp& Timestamp::operator+=(Duration duration) {
356 return *this = (*this + duration);
357 }
358
359 void TestOnlySetProcessEpoch(gpr_timespec epoch);
360
361 std::ostream& operator<<(std::ostream& out, Timestamp timestamp);
362 std::ostream& operator<<(std::ostream& out, Duration duration);
363
364 } // namespace grpc_core
365
366 #endif // GRPC_SRC_CORE_LIB_GPRPP_TIME_H
367