Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:31:55

0001 // Copyright 2017 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 
0015 #ifndef ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
0016 #define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
0017 
0018 #ifndef _WIN32
0019 #include <sys/types.h>
0020 #endif
0021 
0022 #include <algorithm>
0023 #include <chrono>  // NOLINT(build/c++11)
0024 #include <cstdint>
0025 #include <ctime>
0026 #include <limits>
0027 
0028 #include "absl/base/config.h"
0029 #include "absl/base/internal/raw_logging.h"
0030 #include "absl/time/clock.h"
0031 #include "absl/time/time.h"
0032 
0033 namespace absl {
0034 ABSL_NAMESPACE_BEGIN
0035 namespace synchronization_internal {
0036 
0037 // An optional timeout, with nanosecond granularity.
0038 //
0039 // This is a private low-level API for use by a handful of low-level
0040 // components. Higher-level components should build APIs based on
0041 // absl::Time and absl::Duration.
0042 class KernelTimeout {
0043  public:
0044   // Construct an absolute timeout that should expire at `t`.
0045   explicit KernelTimeout(absl::Time t);
0046 
0047   // Construct a relative timeout that should expire after `d`.
0048   explicit KernelTimeout(absl::Duration d);
0049 
0050   // Infinite timeout.
0051   constexpr KernelTimeout() : rep_(kNoTimeout) {}
0052 
0053   // A more explicit factory for those who prefer it.
0054   // Equivalent to `KernelTimeout()`.
0055   static constexpr KernelTimeout Never() { return KernelTimeout(); }
0056 
0057   // Returns true if there is a timeout that will eventually expire.
0058   // Returns false if the timeout is infinite.
0059   bool has_timeout() const { return rep_ != kNoTimeout; }
0060 
0061   // If `has_timeout()` is true, returns true if the timeout was provided as an
0062   // `absl::Time`. The return value is undefined if `has_timeout()` is false
0063   // because all indefinite timeouts are equivalent.
0064   bool is_absolute_timeout() const { return (rep_ & 1) == 0; }
0065 
0066   // If `has_timeout()` is true, returns true if the timeout was provided as an
0067   // `absl::Duration`. The return value is undefined if `has_timeout()` is false
0068   // because all indefinite timeouts are equivalent.
0069   bool is_relative_timeout() const { return (rep_ & 1) == 1; }
0070 
0071   // Convert to `struct timespec` for interfaces that expect an absolute
0072   // timeout. If !has_timeout() or is_relative_timeout(), attempts to convert to
0073   // a reasonable absolute timeout, but callers should to test has_timeout() and
0074   // is_relative_timeout() and prefer to use a more appropriate interface.
0075   struct timespec MakeAbsTimespec() const;
0076 
0077   // Convert to `struct timespec` for interfaces that expect a relative
0078   // timeout. If !has_timeout() or is_absolute_timeout(), attempts to convert to
0079   // a reasonable relative timeout, but callers should to test has_timeout() and
0080   // is_absolute_timeout() and prefer to use a more appropriate interface. Since
0081   // the return value is a relative duration, it should be recomputed by calling
0082   // this method in the case of a spurious wakeup.
0083   struct timespec MakeRelativeTimespec() const;
0084 
0085 #ifndef _WIN32
0086   // Convert to `struct timespec` for interfaces that expect an absolute timeout
0087   // on a specific clock `c`. This is similar to `MakeAbsTimespec()`, but
0088   // callers usually want to use this method with `CLOCK_MONOTONIC` when
0089   // relative timeouts are requested, and when the appropriate interface expects
0090   // an absolute timeout relative to a specific clock (for example,
0091   // pthread_cond_clockwait() or sem_clockwait()). If !has_timeout(), attempts
0092   // to convert to a reasonable absolute timeout, but callers should to test
0093   // has_timeout() prefer to use a more appropriate interface.
0094   struct timespec MakeClockAbsoluteTimespec(clockid_t c) const;
0095 #endif
0096 
0097   // Convert to unix epoch nanos for interfaces that expect an absolute timeout
0098   // in nanoseconds. If !has_timeout() or is_relative_timeout(), attempts to
0099   // convert to a reasonable absolute timeout, but callers should to test
0100   // has_timeout() and is_relative_timeout() and prefer to use a more
0101   // appropriate interface.
0102   int64_t MakeAbsNanos() const;
0103 
0104   // Converts to milliseconds from now, or INFINITE when
0105   // !has_timeout(). For use by SleepConditionVariableSRW on
0106   // Windows. Callers should recognize that the return value is a
0107   // relative duration (it should be recomputed by calling this method
0108   // in the case of a spurious wakeup).
0109   // This header file may be included transitively by public header files,
0110   // so we define our own DWORD and INFINITE instead of getting them from
0111   // <intsafe.h> and <WinBase.h>.
0112   typedef unsigned long DWord;  // NOLINT
0113   DWord InMillisecondsFromNow() const;
0114 
0115   // Convert to std::chrono::time_point for interfaces that expect an absolute
0116   // timeout, like std::condition_variable::wait_until(). If !has_timeout() or
0117   // is_relative_timeout(), attempts to convert to a reasonable absolute
0118   // timeout, but callers should test has_timeout() and is_relative_timeout()
0119   // and prefer to use a more appropriate interface.
0120   std::chrono::time_point<std::chrono::system_clock> ToChronoTimePoint() const;
0121 
0122   // Convert to std::chrono::time_point for interfaces that expect a relative
0123   // timeout, like std::condition_variable::wait_for(). If !has_timeout() or
0124   // is_absolute_timeout(), attempts to convert to a reasonable relative
0125   // timeout, but callers should test has_timeout() and is_absolute_timeout()
0126   // and prefer to use a more appropriate interface. Since the return value is a
0127   // relative duration, it should be recomputed by calling this method in the
0128   // case of a spurious wakeup.
0129   std::chrono::nanoseconds ToChronoDuration() const;
0130 
0131   // Returns true if steady (aka monotonic) clocks are supported by the system.
0132   // This method exists because go/btm requires synchronized clocks, and
0133   // thus requires we use the system (aka walltime) clock.
0134   static constexpr bool SupportsSteadyClock() { return true; }
0135 
0136  private:
0137   // Returns the current time, expressed as a count of nanoseconds since the
0138   // epoch used by an arbitrary clock. The implementation tries to use a steady
0139   // (monotonic) clock if one is available.
0140   static int64_t SteadyClockNow();
0141 
0142   // Internal representation.
0143   //   - If the value is kNoTimeout, then the timeout is infinite, and
0144   //     has_timeout() will return true.
0145   //   - If the low bit is 0, then the high 63 bits is the number of nanoseconds
0146   //     after the unix epoch.
0147   //   - If the low bit is 1, then the high 63 bits is the number of nanoseconds
0148   //     after the epoch used by SteadyClockNow().
0149   //
0150   // In all cases the time is stored as an absolute time, the only difference is
0151   // the clock epoch. The use of absolute times is important since in the case
0152   // of a relative timeout with a spurious wakeup, the program would have to
0153   // restart the wait, and thus needs a way of recomputing the remaining time.
0154   uint64_t rep_;
0155 
0156   // Returns the number of nanoseconds stored in the internal representation.
0157   // When combined with the clock epoch indicated by the low bit (which is
0158   // accessed through is_absolute_timeout() and is_relative_timeout()), the
0159   // return value is used to compute when the timeout should occur.
0160   int64_t RawAbsNanos() const { return static_cast<int64_t>(rep_ >> 1); }
0161 
0162   // Converts to nanoseconds from now. Since the return value is a relative
0163   // duration, it should be recomputed by calling this method in the case of a
0164   // spurious wakeup.
0165   int64_t InNanosecondsFromNow() const;
0166 
0167   // A value that represents no timeout (or an infinite timeout).
0168   static constexpr uint64_t kNoTimeout = (std::numeric_limits<uint64_t>::max)();
0169 
0170   // The maximum value that can be stored in the high 63 bits.
0171   static constexpr int64_t kMaxNanos = (std::numeric_limits<int64_t>::max)();
0172 };
0173 
0174 }  // namespace synchronization_internal
0175 ABSL_NAMESPACE_END
0176 }  // namespace absl
0177 
0178 #endif  // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_