capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

timer.h (6075B)


      1 // Copyright (c) 2014 Google Inc. (contributed by Remy Blank <rblank@google.com>)
      2 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
      3 // Licensed under the MIT License:
      4 //
      5 // Permission is hereby granted, free of charge, to any person obtaining a copy
      6 // of this software and associated documentation files (the "Software"), to deal
      7 // in the Software without restriction, including without limitation the rights
      8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      9 // copies of the Software, and to permit persons to whom the Software is
     10 // furnished to do so, subject to the following conditions:
     11 //
     12 // The above copyright notice and this permission notice shall be included in
     13 // all copies or substantial portions of the Software.
     14 //
     15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     21 // THE SOFTWARE.
     22 
     23 #pragma once
     24 
     25 #include "time.h"
     26 #include "async.h"
     27 
     28 KJ_BEGIN_HEADER
     29 
     30 namespace kj {
     31 
     32 class Timer: public MonotonicClock {
     33   // Interface to time and timer functionality.
     34   //
     35   // Each `Timer` may have a different origin, and some `Timer`s may in fact tick at a different
     36   // rate than real time (e.g. a `Timer` could represent CPU time consumed by a thread).  However,
     37   // all `Timer`s are monotonic: time will never appear to move backwards, even if the calendar
     38   // date as tracked by the system is manually modified.
     39   //
     40   // That said, the `Timer` returned by `kj::setupAsyncIo().provider->getTimer()` in particular is
     41   // guaranteed to be synchronized with the `MonotonicClock` returned by
     42   // `systemPreciseMonotonicClock()` (or, more precisely, is updated to match that clock whenever
     43   // the loop waits).
     44   //
     45   // Note that the value returned by `Timer::now()` only changes each time the
     46   // event loop waits for I/O from the system. While the event loop is actively
     47   // running, the time stays constant. This is intended to make behavior more
     48   // deterministic and reproducible. However, if you need up-to-the-cycle
     49   // accurate time, then `Timer::now()` is not appropriate. Instead, use
     50   // `systemPreciseMonotonicClock()` directly in this case.
     51 
     52 public:
     53   virtual TimePoint now() const = 0;
     54   // Returns the current value of a clock that moves steadily forward, independent of any
     55   // changes in the wall clock. The value is updated every time the event loop waits,
     56   // and is constant in-between waits.
     57 
     58   virtual Promise<void> atTime(TimePoint time) = 0;
     59   // Returns a promise that returns as soon as now() >= time.
     60 
     61   virtual Promise<void> afterDelay(Duration delay) = 0;
     62   // Equivalent to atTime(now() + delay).
     63 
     64   template <typename T>
     65   Promise<T> timeoutAt(TimePoint time, Promise<T>&& promise) KJ_WARN_UNUSED_RESULT;
     66   // Return a promise equivalent to `promise` but which throws an exception (and cancels the
     67   // original promise) if it hasn't completed by `time`. The thrown exception is of type
     68   // "OVERLOADED".
     69 
     70   template <typename T>
     71   Promise<T> timeoutAfter(Duration delay, Promise<T>&& promise) KJ_WARN_UNUSED_RESULT;
     72   // Return a promise equivalent to `promise` but which throws an exception (and cancels the
     73   // original promise) if it hasn't completed after `delay` from now. The thrown exception is of
     74   // type "OVERLOADED".
     75 
     76 private:
     77   static kj::Exception makeTimeoutException();
     78 };
     79 
     80 class TimerImpl final: public Timer {
     81   // Implementation of Timer that expects an external caller -- usually, the EventPort
     82   // implementation -- to tell it when time has advanced.
     83 
     84 public:
     85   TimerImpl(TimePoint startTime);
     86   ~TimerImpl() noexcept(false);
     87 
     88   Maybe<TimePoint> nextEvent();
     89   // Returns the time at which the next scheduled timer event will occur, or null if no timer
     90   // events are scheduled.
     91 
     92   Maybe<uint64_t> timeoutToNextEvent(TimePoint start, Duration unit, uint64_t max);
     93   // Convenience method which computes a timeout value to pass to an event-waiting system call to
     94   // cause it to time out when the next timer event occurs.
     95   //
     96   // `start` is the time at which the timeout starts counting. This is typically not the same as
     97   // now() since some time may have passed since the last time advanceTo() was called.
     98   //
     99   // `unit` is the time unit in which the timeout is measured. This is often MILLISECONDS. Note
    100   // that this method will fractional values *up*, to guarantee that the returned timeout waits
    101   // until just *after* the time the event is scheduled.
    102   //
    103   // The timeout will be clamped to `max`. Use this to avoid an overflow if e.g. the OS wants a
    104   // 32-bit value or a signed value.
    105   //
    106   // Returns nullptr if there are no future events.
    107 
    108   void advanceTo(TimePoint newTime);
    109   // Set the time to `time` and fire any at() events that have been passed.
    110 
    111   // implements Timer ----------------------------------------------------------
    112   TimePoint now() const override;
    113   Promise<void> atTime(TimePoint time) override;
    114   Promise<void> afterDelay(Duration delay) override;
    115 
    116 private:
    117   struct Impl;
    118   class TimerPromiseAdapter;
    119   TimePoint time;
    120   Own<Impl> impl;
    121 };
    122 
    123 // =======================================================================================
    124 // inline implementation details
    125 
    126 template <typename T>
    127 Promise<T> Timer::timeoutAt(TimePoint time, Promise<T>&& promise) {
    128   return promise.exclusiveJoin(atTime(time).then([]() -> kj::Promise<T> {
    129     return makeTimeoutException();
    130   }));
    131 }
    132 
    133 template <typename T>
    134 Promise<T> Timer::timeoutAfter(Duration delay, Promise<T>&& promise) {
    135   return promise.exclusiveJoin(afterDelay(delay).then([]() -> kj::Promise<T> {
    136     return makeTimeoutException();
    137   }));
    138 }
    139 
    140 inline TimePoint TimerImpl::now() const { return time; }
    141 
    142 }  // namespace kj
    143 
    144 KJ_END_HEADER