summaryrefslogtreecommitdiff
path: root/absl/synchronization/internal/kernel_timeout.h
diff options
context:
space:
mode:
authorGravatar Derek Mauro <dmauro@google.com>2023-03-13 13:24:00 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2023-03-13 13:24:46 -0700
commit7f47b00fca75bee477c8a2e3e8fc74a1cf7c743f (patch)
tree633a58707b877d90b271ae7cbe85388a7262e2c5 /absl/synchronization/internal/kernel_timeout.h
parentac8afe6c78d4bde66c8bcf2f3dd9fefea7d4fac8 (diff)
Synchronization: Change KernelTimeout to always store absolute
timeouts, but when a relative timeout is provided, the timeout is an absolute timeout against a steady clock (when possible). This allows methods that return relative timeouts to automatically recompute the remaining duration, for instance, on suprious wakeups. PiperOrigin-RevId: 516304139 Change-Id: I7d739cb50dd749eba5dba7ac6c34d18dc53703ed
Diffstat (limited to 'absl/synchronization/internal/kernel_timeout.h')
-rw-r--r--absl/synchronization/internal/kernel_timeout.h24
1 files changed, 19 insertions, 5 deletions
diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h
index f7c40337..e2cf3c2a 100644
--- a/absl/synchronization/internal/kernel_timeout.h
+++ b/absl/synchronization/internal/kernel_timeout.h
@@ -75,7 +75,9 @@ class KernelTimeout {
// Convert to `struct timespec` for interfaces that expect a relative
// timeout. If !has_timeout() or is_absolute_timeout(), attempts to convert to
// a reasonable relative timeout, but callers should to test has_timeout() and
- // is_absolute_timeout() and prefer to use a more appropriate interface.
+ // is_absolute_timeout() and prefer to use a more appropriate interface. Since
+ // the return value is a relative duration, it should be recomputed by calling
+ // this method in the case of a spurious wakeup.
struct timespec MakeRelativeTimespec() const;
// Convert to unix epoch nanos for interfaces that expect an absolute timeout
@@ -107,17 +109,24 @@ class KernelTimeout {
// timeout, like std::condition_variable::wait_for(). If !has_timeout() or
// is_absolute_timeout(), attempts to convert to a reasonable relative
// timeout, but callers should test has_timeout() and is_absolute_timeout()
- // and prefer to use a more appropriate interface.
+ // and prefer to use a more appropriate interface. Since the return value is a
+ // relative duration, it should be recomputed by calling this method in the
+ // case of a spurious wakeup.
std::chrono::nanoseconds ToChronoDuration() const;
private:
+ // Returns the current time, expressed as a count of nanoseconds since the
+ // epoch used by an arbitrary clock. The implementation tries to use a steady
+ // (monotonic) clock if one is available.
+ static int64_t SteadyClockNow();
+
// Internal representation.
// - If the value is kNoTimeout, then the timeout is infinite, and
// has_timeout() will return true.
- // - If the low bit is 0, then the high 63 bits is number of nanoseconds
+ // - If the low bit is 0, then the high 63 bits is the number of nanoseconds
// after the unix epoch.
- // - If the low bit is 1, then the high 63 bits is a relative duration in
- // nanoseconds.
+ // - If the low bit is 1, then the high 63 bits is the number of nanoseconds
+ // after the epoch used by SteadyClockNow().
uint64_t rep_;
// Returns the number of nanoseconds stored in the internal representation.
@@ -125,6 +134,11 @@ class KernelTimeout {
// value is used to compute when the timeout should occur.
int64_t RawNanos() const { return static_cast<int64_t>(rep_ >> 1); }
+ // Converts to nanoseconds from now. Since the return value is a relative
+ // duration, it should be recomputed by calling this method in the case of a
+ // spurious wakeup.
+ int64_t InNanosecondsFromNow() const;
+
// A value that represents no timeout (or an infinite timeout).
static constexpr uint64_t kNoTimeout = (std::numeric_limits<uint64_t>::max)();