07c0c41d1790bd44f953f03e674a20cfde9ab99a
[folly.git] / folly / futures / Timekeeper.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 #include <folly/futures/detail/Types.h>
20
21 namespace folly {
22
23 template <class> struct Future;
24
25 /// A Timekeeper handles the details of keeping time and fulfilling delay
26 /// promises. The returned Future<void> will either complete after the
27 /// elapsed time, or in the event of some kind of exceptional error may hold
28 /// an exception. These Futures respond to cancellation. If you use a lot of
29 /// Delays and many of them ultimately are unneeded (as would be the case for
30 /// Delays that are used to trigger timeouts of async operations), then you
31 /// can and should cancel them to reclaim resources.
32 ///
33 /// Users will typically get one of these via Future::sleep(Duration) or
34 /// use them implicitly behind the scenes by passing a timeout to some Future
35 /// operation.
36 ///
37 /// Although we don't formally alias Delay = Future<void>,
38 /// that's an appropriate term for it. People will probably also call these
39 /// Timeouts, and that's ok I guess, but that term is so overloaded I thought
40 /// it made sense to introduce a cleaner term.
41 ///
42 /// Remember that Duration is a std::chrono duration (millisecond resolution
43 /// at the time of writing).
44 class Timekeeper {
45  public:
46   virtual ~Timekeeper() = default;
47
48   /// Returns a future that will complete after the given duration with the
49   /// elapsed time. Exceptional errors can happen but they must be
50   /// exceptional. Use the steady (monotonic) clock.
51   ///
52   /// You may cancel this Future to reclaim resources.
53   ///
54   /// This future probably completes on the timer thread. You should almost
55   /// certainly follow it with a via() call or the accuracy of other timers
56   /// will suffer.
57   virtual Future<void> after(Duration) = 0;
58
59   /// Returns a future that will complete at the requested time.
60   ///
61   /// You may cancel this Future to reclaim resources.
62   ///
63   /// NB This is sugar for `after(when - now)`, so while you are welcome to
64   /// use a std::chrono::system_clock::time_point it will not track changes to
65   /// the system clock but rather execute that many milliseconds in the future
66   /// according to the steady clock.
67   template <class Clock>
68   Future<void> at(std::chrono::time_point<Clock> when);
69 };
70
71 } // namespace folly
72
73 // now get those definitions
74 #include <folly/futures/Future.h>
75
76 // finally we can use Future
77 namespace folly {
78
79 template <class Clock>
80 Future<void> Timekeeper::at(std::chrono::time_point<Clock> when) {
81   auto now = Clock::now();
82
83   if (when <= now) {
84     return makeFuture();
85   }
86
87   return after(when - now);
88 }
89
90 } // namespace folly