duration.cc (31154B)
1 // Copyright 2017 The Abseil 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 // https://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 // The implementation of the absl::Duration class, which is declared in 16 // //absl/time.h. This class behaves like a numeric type; it has no public 17 // methods and is used only through the operators defined here. 18 // 19 // Implementation notes: 20 // 21 // An absl::Duration is represented as 22 // 23 // rep_hi_ : (int64_t) Whole seconds 24 // rep_lo_ : (uint32_t) Fractions of a second 25 // 26 // The seconds value (rep_hi_) may be positive or negative as appropriate. 27 // The fractional seconds (rep_lo_) is always a positive offset from rep_hi_. 28 // The API for Duration guarantees at least nanosecond resolution, which 29 // means rep_lo_ could have a max value of 1B - 1 if it stored nanoseconds. 30 // However, to utilize more of the available 32 bits of space in rep_lo_, 31 // we instead store quarters of a nanosecond in rep_lo_ resulting in a max 32 // value of 4B - 1. This allows us to correctly handle calculations like 33 // 0.5 nanos + 0.5 nanos = 1 nano. The following example shows the actual 34 // Duration rep using quarters of a nanosecond. 35 // 36 // 2.5 sec = {rep_hi_=2, rep_lo_=2000000000} // lo = 4 * 500000000 37 // -2.5 sec = {rep_hi_=-3, rep_lo_=2000000000} 38 // 39 // Infinite durations are represented as Durations with the rep_lo_ field set 40 // to all 1s. 41 // 42 // +InfiniteDuration: 43 // rep_hi_ : kint64max 44 // rep_lo_ : ~0U 45 // 46 // -InfiniteDuration: 47 // rep_hi_ : kint64min 48 // rep_lo_ : ~0U 49 // 50 // Arithmetic overflows/underflows to +/- infinity and saturates. 51 52 #if defined(_MSC_VER) 53 #include <winsock2.h> // for timeval 54 #endif 55 56 #include <algorithm> 57 #include <cassert> 58 #include <chrono> // NOLINT(build/c++11) 59 #include <cmath> 60 #include <cstdint> 61 #include <cstdlib> 62 #include <cstring> 63 #include <ctime> 64 #include <functional> 65 #include <limits> 66 #include <string> 67 68 #include "absl/base/attributes.h" 69 #include "absl/base/casts.h" 70 #include "absl/base/config.h" 71 #include "absl/numeric/int128.h" 72 #include "absl/strings/string_view.h" 73 #include "absl/strings/strip.h" 74 #include "absl/time/time.h" 75 76 namespace absl { 77 ABSL_NAMESPACE_BEGIN 78 79 namespace { 80 81 using time_internal::kTicksPerNanosecond; 82 using time_internal::kTicksPerSecond; 83 84 constexpr int64_t kint64max = std::numeric_limits<int64_t>::max(); 85 constexpr int64_t kint64min = std::numeric_limits<int64_t>::min(); 86 87 // Can't use std::isinfinite() because it doesn't exist on windows. 88 inline bool IsFinite(double d) { 89 if (std::isnan(d)) return false; 90 return d != std::numeric_limits<double>::infinity() && 91 d != -std::numeric_limits<double>::infinity(); 92 } 93 94 inline bool IsValidDivisor(double d) { 95 if (std::isnan(d)) return false; 96 return d != 0.0; 97 } 98 99 // *sec may be positive or negative. *ticks must be in the range 100 // -kTicksPerSecond < *ticks < kTicksPerSecond. If *ticks is negative it 101 // will be normalized to a positive value by adjusting *sec accordingly. 102 inline void NormalizeTicks(int64_t* sec, int64_t* ticks) { 103 if (*ticks < 0) { 104 --*sec; 105 *ticks += kTicksPerSecond; 106 } 107 } 108 109 // Makes a uint128 from the absolute value of the given scalar. 110 inline uint128 MakeU128(int64_t a) { 111 uint128 u128 = 0; 112 if (a < 0) { 113 ++u128; 114 ++a; // Makes it safe to negate 'a' 115 a = -a; 116 } 117 u128 += static_cast<uint64_t>(a); 118 return u128; 119 } 120 121 // Makes a uint128 count of ticks out of the absolute value of the Duration. 122 inline uint128 MakeU128Ticks(Duration d) { 123 int64_t rep_hi = time_internal::GetRepHi(d); 124 uint32_t rep_lo = time_internal::GetRepLo(d); 125 if (rep_hi < 0) { 126 ++rep_hi; 127 rep_hi = -rep_hi; 128 rep_lo = kTicksPerSecond - rep_lo; 129 } 130 uint128 u128 = static_cast<uint64_t>(rep_hi); 131 u128 *= static_cast<uint64_t>(kTicksPerSecond); 132 u128 += rep_lo; 133 return u128; 134 } 135 136 // Breaks a uint128 of ticks into a Duration. 137 inline Duration MakeDurationFromU128(uint128 u128, bool is_neg) { 138 int64_t rep_hi; 139 uint32_t rep_lo; 140 const uint64_t h64 = Uint128High64(u128); 141 const uint64_t l64 = Uint128Low64(u128); 142 if (h64 == 0) { // fastpath 143 const uint64_t hi = l64 / kTicksPerSecond; 144 rep_hi = static_cast<int64_t>(hi); 145 rep_lo = static_cast<uint32_t>(l64 - hi * kTicksPerSecond); 146 } else { 147 // kMaxRepHi64 is the high 64 bits of (2^63 * kTicksPerSecond). 148 // Any positive tick count whose high 64 bits are >= kMaxRepHi64 149 // is not representable as a Duration. A negative tick count can 150 // have its high 64 bits == kMaxRepHi64 but only when the low 64 151 // bits are all zero, otherwise it is not representable either. 152 const uint64_t kMaxRepHi64 = 0x77359400UL; 153 if (h64 >= kMaxRepHi64) { 154 if (is_neg && h64 == kMaxRepHi64 && l64 == 0) { 155 // Avoid trying to represent -kint64min below. 156 return time_internal::MakeDuration(kint64min); 157 } 158 return is_neg ? -InfiniteDuration() : InfiniteDuration(); 159 } 160 const uint128 kTicksPerSecond128 = static_cast<uint64_t>(kTicksPerSecond); 161 const uint128 hi = u128 / kTicksPerSecond128; 162 rep_hi = static_cast<int64_t>(Uint128Low64(hi)); 163 rep_lo = 164 static_cast<uint32_t>(Uint128Low64(u128 - hi * kTicksPerSecond128)); 165 } 166 if (is_neg) { 167 rep_hi = -rep_hi; 168 if (rep_lo != 0) { 169 --rep_hi; 170 rep_lo = kTicksPerSecond - rep_lo; 171 } 172 } 173 return time_internal::MakeDuration(rep_hi, rep_lo); 174 } 175 176 // Convert between int64_t and uint64_t, preserving representation. This 177 // allows us to do arithmetic in the unsigned domain, where overflow has 178 // well-defined behavior. See operator+=() and operator-=(). 179 // 180 // C99 7.20.1.1.1, as referenced by C++11 18.4.1.2, says, "The typedef 181 // name intN_t designates a signed integer type with width N, no padding 182 // bits, and a two's complement representation." So, we can convert to 183 // and from the corresponding uint64_t value using a bit cast. 184 inline uint64_t EncodeTwosComp(int64_t v) { 185 return absl::bit_cast<uint64_t>(v); 186 } 187 inline int64_t DecodeTwosComp(uint64_t v) { return absl::bit_cast<int64_t>(v); } 188 189 // Note: The overflow detection in this function is done using greater/less *or 190 // equal* because kint64max/min is too large to be represented exactly in a 191 // double (which only has 53 bits of precision). In order to avoid assigning to 192 // rep->hi a double value that is too large for an int64_t (and therefore is 193 // undefined), we must consider computations that equal kint64max/min as a 194 // double as overflow cases. 195 inline bool SafeAddRepHi(double a_hi, double b_hi, Duration* d) { 196 double c = a_hi + b_hi; 197 if (c >= static_cast<double>(kint64max)) { 198 *d = InfiniteDuration(); 199 return false; 200 } 201 if (c <= static_cast<double>(kint64min)) { 202 *d = -InfiniteDuration(); 203 return false; 204 } 205 *d = time_internal::MakeDuration(static_cast<int64_t>(c), 206 time_internal::GetRepLo(*d)); 207 return true; 208 } 209 210 // A functor that's similar to std::multiplies<T>, except this returns the max 211 // T value instead of overflowing. This is only defined for uint128. 212 template <typename Ignored> 213 struct SafeMultiply { 214 uint128 operator()(uint128 a, uint128 b) const { 215 // b hi is always zero because it originated as an int64_t. 216 assert(Uint128High64(b) == 0); 217 // Fastpath to avoid the expensive overflow check with division. 218 if (Uint128High64(a) == 0) { 219 return (((Uint128Low64(a) | Uint128Low64(b)) >> 32) == 0) 220 ? static_cast<uint128>(Uint128Low64(a) * Uint128Low64(b)) 221 : a * b; 222 } 223 return b == 0 ? b : (a > Uint128Max() / b) ? Uint128Max() : a * b; 224 } 225 }; 226 227 // Scales (i.e., multiplies or divides, depending on the Operation template) 228 // the Duration d by the int64_t r. 229 template <template <typename> class Operation> 230 inline Duration ScaleFixed(Duration d, int64_t r) { 231 const uint128 a = MakeU128Ticks(d); 232 const uint128 b = MakeU128(r); 233 const uint128 q = Operation<uint128>()(a, b); 234 const bool is_neg = (time_internal::GetRepHi(d) < 0) != (r < 0); 235 return MakeDurationFromU128(q, is_neg); 236 } 237 238 // Scales (i.e., multiplies or divides, depending on the Operation template) 239 // the Duration d by the double r. 240 template <template <typename> class Operation> 241 inline Duration ScaleDouble(Duration d, double r) { 242 Operation<double> op; 243 double hi_doub = op(static_cast<double>(time_internal::GetRepHi(d)), r); 244 double lo_doub = op(static_cast<double>(time_internal::GetRepLo(d)), r); 245 246 double hi_int = 0; 247 double hi_frac = std::modf(hi_doub, &hi_int); 248 249 // Moves hi's fractional bits to lo. 250 lo_doub /= kTicksPerSecond; 251 lo_doub += hi_frac; 252 253 double lo_int = 0; 254 double lo_frac = std::modf(lo_doub, &lo_int); 255 256 // Rolls lo into hi if necessary. 257 int64_t lo64 = static_cast<int64_t>(std::round(lo_frac * kTicksPerSecond)); 258 259 Duration ans; 260 if (!SafeAddRepHi(hi_int, lo_int, &ans)) return ans; 261 int64_t hi64 = time_internal::GetRepHi(ans); 262 if (!SafeAddRepHi(static_cast<double>(hi64), 263 static_cast<double>(lo64 / kTicksPerSecond), &ans)) { 264 return ans; 265 } 266 hi64 = time_internal::GetRepHi(ans); 267 lo64 %= kTicksPerSecond; 268 NormalizeTicks(&hi64, &lo64); 269 return time_internal::MakeDuration(hi64, lo64); 270 } 271 272 // Tries to divide num by den as fast as possible by looking for common, easy 273 // cases. If the division was done, the quotient is in *q and the remainder is 274 // in *rem and true will be returned. 275 inline bool IDivFastPath(const Duration num, const Duration den, int64_t* q, 276 Duration* rem) { 277 // Bail if num or den is an infinity. 278 if (time_internal::IsInfiniteDuration(num) || 279 time_internal::IsInfiniteDuration(den)) 280 return false; 281 282 int64_t num_hi = time_internal::GetRepHi(num); 283 uint32_t num_lo = time_internal::GetRepLo(num); 284 int64_t den_hi = time_internal::GetRepHi(den); 285 uint32_t den_lo = time_internal::GetRepLo(den); 286 287 if (den_hi == 0) { 288 if (den_lo == kTicksPerNanosecond) { 289 // Dividing by 1ns 290 if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000000) { 291 *q = num_hi * 1000000000 + num_lo / kTicksPerNanosecond; 292 *rem = time_internal::MakeDuration(0, num_lo % den_lo); 293 return true; 294 } 295 } else if (den_lo == 100 * kTicksPerNanosecond) { 296 // Dividing by 100ns (common when converting to Universal time) 297 if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 10000000) { 298 *q = num_hi * 10000000 + num_lo / (100 * kTicksPerNanosecond); 299 *rem = time_internal::MakeDuration(0, num_lo % den_lo); 300 return true; 301 } 302 } else if (den_lo == 1000 * kTicksPerNanosecond) { 303 // Dividing by 1us 304 if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000) { 305 *q = num_hi * 1000000 + num_lo / (1000 * kTicksPerNanosecond); 306 *rem = time_internal::MakeDuration(0, num_lo % den_lo); 307 return true; 308 } 309 } else if (den_lo == 1000000 * kTicksPerNanosecond) { 310 // Dividing by 1ms 311 if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000) { 312 *q = num_hi * 1000 + num_lo / (1000000 * kTicksPerNanosecond); 313 *rem = time_internal::MakeDuration(0, num_lo % den_lo); 314 return true; 315 } 316 } 317 } else if (den_hi > 0 && den_lo == 0) { 318 // Dividing by positive multiple of 1s 319 if (num_hi >= 0) { 320 if (den_hi == 1) { 321 *q = num_hi; 322 *rem = time_internal::MakeDuration(0, num_lo); 323 return true; 324 } 325 *q = num_hi / den_hi; 326 *rem = time_internal::MakeDuration(num_hi % den_hi, num_lo); 327 return true; 328 } 329 if (num_lo != 0) { 330 num_hi += 1; 331 } 332 int64_t quotient = num_hi / den_hi; 333 int64_t rem_sec = num_hi % den_hi; 334 if (rem_sec > 0) { 335 rem_sec -= den_hi; 336 quotient += 1; 337 } 338 if (num_lo != 0) { 339 rem_sec -= 1; 340 } 341 *q = quotient; 342 *rem = time_internal::MakeDuration(rem_sec, num_lo); 343 return true; 344 } 345 346 return false; 347 } 348 349 } // namespace 350 351 namespace { 352 353 int64_t IDivSlowPath(bool satq, const Duration num, const Duration den, 354 Duration* rem) { 355 const bool num_neg = num < ZeroDuration(); 356 const bool den_neg = den < ZeroDuration(); 357 const bool quotient_neg = num_neg != den_neg; 358 359 if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) { 360 *rem = num_neg ? -InfiniteDuration() : InfiniteDuration(); 361 return quotient_neg ? kint64min : kint64max; 362 } 363 if (time_internal::IsInfiniteDuration(den)) { 364 *rem = num; 365 return 0; 366 } 367 368 const uint128 a = MakeU128Ticks(num); 369 const uint128 b = MakeU128Ticks(den); 370 uint128 quotient128 = a / b; 371 372 if (satq) { 373 // Limits the quotient to the range of int64_t. 374 if (quotient128 > uint128(static_cast<uint64_t>(kint64max))) { 375 quotient128 = quotient_neg ? uint128(static_cast<uint64_t>(kint64min)) 376 : uint128(static_cast<uint64_t>(kint64max)); 377 } 378 } 379 380 const uint128 remainder128 = a - quotient128 * b; 381 *rem = MakeDurationFromU128(remainder128, num_neg); 382 383 if (!quotient_neg || quotient128 == 0) { 384 return Uint128Low64(quotient128) & kint64max; 385 } 386 // The quotient needs to be negated, but we need to carefully handle 387 // quotient128s with the top bit on. 388 return -static_cast<int64_t>(Uint128Low64(quotient128 - 1) & kint64max) - 1; 389 } 390 391 // The 'satq' argument indicates whether the quotient should saturate at the 392 // bounds of int64_t. If it does saturate, the difference will spill over to 393 // the remainder. If it does not saturate, the remainder remain accurate, 394 // but the returned quotient will over/underflow int64_t and should not be used. 395 ABSL_ATTRIBUTE_ALWAYS_INLINE inline int64_t IDivDurationImpl(bool satq, 396 const Duration num, 397 const Duration den, 398 Duration* rem) { 399 int64_t q = 0; 400 if (IDivFastPath(num, den, &q, rem)) { 401 return q; 402 } 403 return IDivSlowPath(satq, num, den, rem); 404 } 405 406 } // namespace 407 408 int64_t IDivDuration(Duration num, Duration den, Duration* rem) { 409 return IDivDurationImpl(true, num, den, 410 rem); // trunc towards zero 411 } 412 413 // 414 // Additive operators. 415 // 416 417 Duration& Duration::operator+=(Duration rhs) { 418 if (time_internal::IsInfiniteDuration(*this)) return *this; 419 if (time_internal::IsInfiniteDuration(rhs)) return *this = rhs; 420 const int64_t orig_rep_hi = rep_hi_.Get(); 421 rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_.Get()) + 422 EncodeTwosComp(rhs.rep_hi_.Get())); 423 if (rep_lo_ >= kTicksPerSecond - rhs.rep_lo_) { 424 rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_.Get()) + 1); 425 rep_lo_ -= kTicksPerSecond; 426 } 427 rep_lo_ += rhs.rep_lo_; 428 if (rhs.rep_hi_.Get() < 0 ? rep_hi_.Get() > orig_rep_hi 429 : rep_hi_.Get() < orig_rep_hi) { 430 return *this = 431 rhs.rep_hi_.Get() < 0 ? -InfiniteDuration() : InfiniteDuration(); 432 } 433 return *this; 434 } 435 436 Duration& Duration::operator-=(Duration rhs) { 437 if (time_internal::IsInfiniteDuration(*this)) return *this; 438 if (time_internal::IsInfiniteDuration(rhs)) { 439 return *this = rhs.rep_hi_.Get() >= 0 ? -InfiniteDuration() 440 : InfiniteDuration(); 441 } 442 const int64_t orig_rep_hi = rep_hi_.Get(); 443 rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_.Get()) - 444 EncodeTwosComp(rhs.rep_hi_.Get())); 445 if (rep_lo_ < rhs.rep_lo_) { 446 rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_.Get()) - 1); 447 rep_lo_ += kTicksPerSecond; 448 } 449 rep_lo_ -= rhs.rep_lo_; 450 if (rhs.rep_hi_.Get() < 0 ? rep_hi_.Get() < orig_rep_hi 451 : rep_hi_.Get() > orig_rep_hi) { 452 return *this = rhs.rep_hi_.Get() >= 0 ? -InfiniteDuration() 453 : InfiniteDuration(); 454 } 455 return *this; 456 } 457 458 // 459 // Multiplicative operators. 460 // 461 462 Duration& Duration::operator*=(int64_t r) { 463 if (time_internal::IsInfiniteDuration(*this)) { 464 const bool is_neg = (r < 0) != (rep_hi_.Get() < 0); 465 return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); 466 } 467 return *this = ScaleFixed<SafeMultiply>(*this, r); 468 } 469 470 Duration& Duration::operator*=(double r) { 471 if (time_internal::IsInfiniteDuration(*this) || !IsFinite(r)) { 472 const bool is_neg = std::signbit(r) != (rep_hi_.Get() < 0); 473 return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); 474 } 475 return *this = ScaleDouble<std::multiplies>(*this, r); 476 } 477 478 Duration& Duration::operator/=(int64_t r) { 479 if (time_internal::IsInfiniteDuration(*this) || r == 0) { 480 const bool is_neg = (r < 0) != (rep_hi_.Get() < 0); 481 return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); 482 } 483 return *this = ScaleFixed<std::divides>(*this, r); 484 } 485 486 Duration& Duration::operator/=(double r) { 487 if (time_internal::IsInfiniteDuration(*this) || !IsValidDivisor(r)) { 488 const bool is_neg = std::signbit(r) != (rep_hi_.Get() < 0); 489 return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); 490 } 491 return *this = ScaleDouble<std::divides>(*this, r); 492 } 493 494 Duration& Duration::operator%=(Duration rhs) { 495 IDivDurationImpl(false, *this, rhs, this); 496 return *this; 497 } 498 499 double FDivDuration(Duration num, Duration den) { 500 // Arithmetic with infinity is sticky. 501 if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) { 502 return (num < ZeroDuration()) == (den < ZeroDuration()) 503 ? std::numeric_limits<double>::infinity() 504 : -std::numeric_limits<double>::infinity(); 505 } 506 if (time_internal::IsInfiniteDuration(den)) return 0.0; 507 508 double a = 509 static_cast<double>(time_internal::GetRepHi(num)) * kTicksPerSecond + 510 time_internal::GetRepLo(num); 511 double b = 512 static_cast<double>(time_internal::GetRepHi(den)) * kTicksPerSecond + 513 time_internal::GetRepLo(den); 514 return a / b; 515 } 516 517 // 518 // Trunc/Floor/Ceil. 519 // 520 521 Duration Trunc(Duration d, Duration unit) { return d - (d % unit); } 522 523 Duration Floor(const Duration d, const Duration unit) { 524 const absl::Duration td = Trunc(d, unit); 525 return td <= d ? td : td - AbsDuration(unit); 526 } 527 528 Duration Ceil(const Duration d, const Duration unit) { 529 const absl::Duration td = Trunc(d, unit); 530 return td >= d ? td : td + AbsDuration(unit); 531 } 532 533 // 534 // Factory functions. 535 // 536 537 Duration DurationFromTimespec(timespec ts) { 538 if (static_cast<uint64_t>(ts.tv_nsec) < 1000 * 1000 * 1000) { 539 int64_t ticks = ts.tv_nsec * kTicksPerNanosecond; 540 return time_internal::MakeDuration(ts.tv_sec, ticks); 541 } 542 return Seconds(ts.tv_sec) + Nanoseconds(ts.tv_nsec); 543 } 544 545 Duration DurationFromTimeval(timeval tv) { 546 if (static_cast<uint64_t>(tv.tv_usec) < 1000 * 1000) { 547 int64_t ticks = tv.tv_usec * 1000 * kTicksPerNanosecond; 548 return time_internal::MakeDuration(tv.tv_sec, ticks); 549 } 550 return Seconds(tv.tv_sec) + Microseconds(tv.tv_usec); 551 } 552 553 // 554 // Conversion to other duration types. 555 // 556 double ToDoubleNanoseconds(Duration d) { 557 return FDivDuration(d, Nanoseconds(1)); 558 } 559 double ToDoubleMicroseconds(Duration d) { 560 return FDivDuration(d, Microseconds(1)); 561 } 562 double ToDoubleMilliseconds(Duration d) { 563 return FDivDuration(d, Milliseconds(1)); 564 } 565 double ToDoubleSeconds(Duration d) { return FDivDuration(d, Seconds(1)); } 566 double ToDoubleMinutes(Duration d) { return FDivDuration(d, Minutes(1)); } 567 double ToDoubleHours(Duration d) { return FDivDuration(d, Hours(1)); } 568 569 timespec ToTimespec(Duration d) { 570 timespec ts; 571 if (!time_internal::IsInfiniteDuration(d)) { 572 int64_t rep_hi = time_internal::GetRepHi(d); 573 uint32_t rep_lo = time_internal::GetRepLo(d); 574 if (rep_hi < 0) { 575 // Tweak the fields so that unsigned division of rep_lo 576 // maps to truncation (towards zero) for the timespec. 577 rep_lo += kTicksPerNanosecond - 1; 578 if (rep_lo >= kTicksPerSecond) { 579 rep_hi += 1; 580 rep_lo -= kTicksPerSecond; 581 } 582 } 583 ts.tv_sec = static_cast<decltype(ts.tv_sec)>(rep_hi); 584 if (ts.tv_sec == rep_hi) { // no time_t narrowing 585 ts.tv_nsec = rep_lo / kTicksPerNanosecond; 586 return ts; 587 } 588 } 589 if (d >= ZeroDuration()) { 590 ts.tv_sec = std::numeric_limits<time_t>::max(); 591 ts.tv_nsec = 1000 * 1000 * 1000 - 1; 592 } else { 593 ts.tv_sec = std::numeric_limits<time_t>::min(); 594 ts.tv_nsec = 0; 595 } 596 return ts; 597 } 598 599 timeval ToTimeval(Duration d) { 600 timeval tv; 601 timespec ts = ToTimespec(d); 602 if (ts.tv_sec < 0) { 603 // Tweak the fields so that positive division of tv_nsec 604 // maps to truncation (towards zero) for the timeval. 605 ts.tv_nsec += 1000 - 1; 606 if (ts.tv_nsec >= 1000 * 1000 * 1000) { 607 ts.tv_sec += 1; 608 ts.tv_nsec -= 1000 * 1000 * 1000; 609 } 610 } 611 tv.tv_sec = static_cast<decltype(tv.tv_sec)>(ts.tv_sec); 612 if (tv.tv_sec != ts.tv_sec) { // narrowing 613 if (ts.tv_sec < 0) { 614 tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min(); 615 tv.tv_usec = 0; 616 } else { 617 tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max(); 618 tv.tv_usec = 1000 * 1000 - 1; 619 } 620 return tv; 621 } 622 tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000); // suseconds_t 623 return tv; 624 } 625 626 std::chrono::nanoseconds ToChronoNanoseconds(Duration d) { 627 return time_internal::ToChronoDuration<std::chrono::nanoseconds>(d); 628 } 629 std::chrono::microseconds ToChronoMicroseconds(Duration d) { 630 return time_internal::ToChronoDuration<std::chrono::microseconds>(d); 631 } 632 std::chrono::milliseconds ToChronoMilliseconds(Duration d) { 633 return time_internal::ToChronoDuration<std::chrono::milliseconds>(d); 634 } 635 std::chrono::seconds ToChronoSeconds(Duration d) { 636 return time_internal::ToChronoDuration<std::chrono::seconds>(d); 637 } 638 std::chrono::minutes ToChronoMinutes(Duration d) { 639 return time_internal::ToChronoDuration<std::chrono::minutes>(d); 640 } 641 std::chrono::hours ToChronoHours(Duration d) { 642 return time_internal::ToChronoDuration<std::chrono::hours>(d); 643 } 644 645 // 646 // To/From string formatting. 647 // 648 649 namespace { 650 651 // Formats a positive 64-bit integer in the given field width. Note that 652 // it is up to the caller of Format64() to ensure that there is sufficient 653 // space before ep to hold the conversion. 654 char* Format64(char* ep, int width, int64_t v) { 655 do { 656 --width; 657 *--ep = static_cast<char>('0' + (v % 10)); // contiguous digits 658 } while (v /= 10); 659 while (--width >= 0) *--ep = '0'; // zero pad 660 return ep; 661 } 662 663 // Helpers for FormatDuration() that format 'n' and append it to 'out' 664 // followed by the given 'unit'. If 'n' formats to "0", nothing is 665 // appended (not even the unit). 666 667 // A type that encapsulates how to display a value of a particular unit. For 668 // values that are displayed with fractional parts, the precision indicates 669 // where to round the value. The precision varies with the display unit because 670 // a Duration can hold only quarters of a nanosecond, so displaying information 671 // beyond that is just noise. 672 // 673 // For example, a microsecond value of 42.00025xxxxx should not display beyond 5 674 // fractional digits, because it is in the noise of what a Duration can 675 // represent. 676 struct DisplayUnit { 677 absl::string_view abbr; 678 int prec; 679 double pow10; 680 }; 681 constexpr DisplayUnit kDisplayNano = {"ns", 2, 1e2}; 682 constexpr DisplayUnit kDisplayMicro = {"us", 5, 1e5}; 683 constexpr DisplayUnit kDisplayMilli = {"ms", 8, 1e8}; 684 constexpr DisplayUnit kDisplaySec = {"s", 11, 1e11}; 685 constexpr DisplayUnit kDisplayMin = {"m", -1, 0.0}; // prec ignored 686 constexpr DisplayUnit kDisplayHour = {"h", -1, 0.0}; // prec ignored 687 688 void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) { 689 char buf[sizeof("2562047788015216")]; // hours in max duration 690 char* const ep = buf + sizeof(buf); 691 char* bp = Format64(ep, 0, n); 692 if (*bp != '0' || bp + 1 != ep) { 693 out->append(bp, static_cast<size_t>(ep - bp)); 694 out->append(unit.abbr.data(), unit.abbr.size()); 695 } 696 } 697 698 // Note: unit.prec is limited to double's digits10 value (typically 15) so it 699 // always fits in buf[]. 700 void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) { 701 constexpr int kBufferSize = std::numeric_limits<double>::digits10; 702 const int prec = std::min(kBufferSize, unit.prec); 703 char buf[kBufferSize]; // also large enough to hold integer part 704 char* ep = buf + sizeof(buf); 705 double d = 0; 706 int64_t frac_part = 707 static_cast<int64_t>(std::round(std::modf(n, &d) * unit.pow10)); 708 int64_t int_part = static_cast<int64_t>(d); 709 if (int_part != 0 || frac_part != 0) { 710 char* bp = Format64(ep, 0, int_part); // always < 1000 711 out->append(bp, static_cast<size_t>(ep - bp)); 712 if (frac_part != 0) { 713 out->push_back('.'); 714 bp = Format64(ep, prec, frac_part); 715 while (ep[-1] == '0') --ep; 716 out->append(bp, static_cast<size_t>(ep - bp)); 717 } 718 out->append(unit.abbr.data(), unit.abbr.size()); 719 } 720 } 721 722 } // namespace 723 724 // From Go's doc at https://golang.org/pkg/time/#Duration.String 725 // [FormatDuration] returns a string representing the duration in the 726 // form "72h3m0.5s". Leading zero units are omitted. As a special 727 // case, durations less than one second format use a smaller unit 728 // (milli-, micro-, or nanoseconds) to ensure that the leading digit 729 // is non-zero. 730 // Unlike Go, we format the zero duration as 0, with no unit. 731 std::string FormatDuration(Duration d) { 732 constexpr Duration kMinDuration = Seconds(kint64min); 733 std::string s; 734 if (d == kMinDuration) { 735 // Avoid needing to negate kint64min by directly returning what the 736 // following code should produce in that case. 737 s = "-2562047788015215h30m8s"; 738 return s; 739 } 740 if (d < ZeroDuration()) { 741 s.append("-"); 742 d = -d; 743 } 744 if (d == InfiniteDuration()) { 745 s.append("inf"); 746 } else if (d < Seconds(1)) { 747 // Special case for durations with a magnitude < 1 second. The duration 748 // is printed as a fraction of a single unit, e.g., "1.2ms". 749 if (d < Microseconds(1)) { 750 AppendNumberUnit(&s, FDivDuration(d, Nanoseconds(1)), kDisplayNano); 751 } else if (d < Milliseconds(1)) { 752 AppendNumberUnit(&s, FDivDuration(d, Microseconds(1)), kDisplayMicro); 753 } else { 754 AppendNumberUnit(&s, FDivDuration(d, Milliseconds(1)), kDisplayMilli); 755 } 756 } else { 757 AppendNumberUnit(&s, IDivDuration(d, Hours(1), &d), kDisplayHour); 758 AppendNumberUnit(&s, IDivDuration(d, Minutes(1), &d), kDisplayMin); 759 AppendNumberUnit(&s, FDivDuration(d, Seconds(1)), kDisplaySec); 760 } 761 if (s.empty() || s == "-") { 762 s = "0"; 763 } 764 return s; 765 } 766 767 namespace { 768 769 // A helper for ParseDuration() that parses a leading number from the given 770 // string and stores the result in *int_part/*frac_part/*frac_scale. The 771 // given string pointer is modified to point to the first unconsumed char. 772 bool ConsumeDurationNumber(const char** dpp, const char* ep, int64_t* int_part, 773 int64_t* frac_part, int64_t* frac_scale) { 774 *int_part = 0; 775 *frac_part = 0; 776 *frac_scale = 1; // invariant: *frac_part < *frac_scale 777 const char* start = *dpp; 778 for (; *dpp != ep; *dpp += 1) { 779 const int d = **dpp - '0'; // contiguous digits 780 if (d < 0 || 10 <= d) break; 781 782 if (*int_part > kint64max / 10) return false; 783 *int_part *= 10; 784 if (*int_part > kint64max - d) return false; 785 *int_part += d; 786 } 787 const bool int_part_empty = (*dpp == start); 788 if (*dpp == ep || **dpp != '.') return !int_part_empty; 789 790 for (*dpp += 1; *dpp != ep; *dpp += 1) { 791 const int d = **dpp - '0'; // contiguous digits 792 if (d < 0 || 10 <= d) break; 793 if (*frac_scale <= kint64max / 10) { 794 *frac_part *= 10; 795 *frac_part += d; 796 *frac_scale *= 10; 797 } 798 } 799 return !int_part_empty || *frac_scale != 1; 800 } 801 802 // A helper for ParseDuration() that parses a leading unit designator (e.g., 803 // ns, us, ms, s, m, h) from the given string and stores the resulting unit 804 // in "*unit". The given string pointer is modified to point to the first 805 // unconsumed char. 806 bool ConsumeDurationUnit(const char** start, const char* end, Duration* unit) { 807 size_t size = static_cast<size_t>(end - *start); 808 switch (size) { 809 case 0: 810 return false; 811 default: 812 switch (**start) { 813 case 'n': 814 if (*(*start + 1) == 's') { 815 *start += 2; 816 *unit = Nanoseconds(1); 817 return true; 818 } 819 break; 820 case 'u': 821 if (*(*start + 1) == 's') { 822 *start += 2; 823 *unit = Microseconds(1); 824 return true; 825 } 826 break; 827 case 'm': 828 if (*(*start + 1) == 's') { 829 *start += 2; 830 *unit = Milliseconds(1); 831 return true; 832 } 833 break; 834 default: 835 break; 836 } 837 ABSL_FALLTHROUGH_INTENDED; 838 case 1: 839 switch (**start) { 840 case 's': 841 *unit = Seconds(1); 842 *start += 1; 843 return true; 844 case 'm': 845 *unit = Minutes(1); 846 *start += 1; 847 return true; 848 case 'h': 849 *unit = Hours(1); 850 *start += 1; 851 return true; 852 default: 853 return false; 854 } 855 } 856 } 857 858 } // namespace 859 860 // From Go's doc at https://golang.org/pkg/time/#ParseDuration 861 // [ParseDuration] parses a duration string. A duration string is 862 // a possibly signed sequence of decimal numbers, each with optional 863 // fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". 864 // Valid time units are "ns", "us" "ms", "s", "m", "h". 865 bool ParseDuration(absl::string_view dur_sv, Duration* d) { 866 int sign = 1; 867 if (absl::ConsumePrefix(&dur_sv, "-")) { 868 sign = -1; 869 } else { 870 absl::ConsumePrefix(&dur_sv, "+"); 871 } 872 if (dur_sv.empty()) return false; 873 874 // Special case for a string of "0". 875 if (dur_sv == "0") { 876 *d = ZeroDuration(); 877 return true; 878 } 879 880 if (dur_sv == "inf") { 881 *d = sign * InfiniteDuration(); 882 return true; 883 } 884 885 const char* start = dur_sv.data(); 886 const char* end = start + dur_sv.size(); 887 888 Duration dur; 889 while (start != end) { 890 int64_t int_part; 891 int64_t frac_part; 892 int64_t frac_scale; 893 Duration unit; 894 if (!ConsumeDurationNumber(&start, end, &int_part, &frac_part, 895 &frac_scale) || 896 !ConsumeDurationUnit(&start, end, &unit)) { 897 return false; 898 } 899 if (int_part != 0) dur += sign * int_part * unit; 900 if (frac_part != 0) dur += sign * frac_part * unit / frac_scale; 901 } 902 *d = dur; 903 return true; 904 } 905 906 bool AbslParseFlag(absl::string_view text, Duration* dst, std::string*) { 907 return ParseDuration(text, dst); 908 } 909 910 std::string AbslUnparseFlag(Duration d) { return FormatDuration(d); } 911 bool ParseFlag(const std::string& text, Duration* dst, std::string* ) { 912 return ParseDuration(text, dst); 913 } 914 915 std::string UnparseFlag(Duration d) { return FormatDuration(d); } 916 917 ABSL_NAMESPACE_END 918 } // namespace absl