Commit 78443cdc authored by Aaryaman Sagar's avatar Aaryaman Sagar Committed by Facebook Github Bot

Remove Timekeeper.h

Summary:
Timekeeper.h had a weird circular dependence issue that would show up when
included from within the future implementation headers.  The stuff in
Timekeeper.h should ideally be within the future headers themselves

Reviewed By: yfeldblum, Orvid

Differential Revision: D7787275

fbshipit-source-id: a6309c0cc5edca4f5bd12d2651c828299681df54
parent cae28c3b
...@@ -220,7 +220,6 @@ nobase_follyinclude_HEADERS = \ ...@@ -220,7 +220,6 @@ nobase_follyinclude_HEADERS = \
futures/SharedPromise.h \ futures/SharedPromise.h \
futures/SharedPromise-inl.h \ futures/SharedPromise-inl.h \
futures/ThreadWheelTimekeeper.h \ futures/ThreadWheelTimekeeper.h \
futures/Timekeeper.h \
futures/detail/Core.h \ futures/detail/Core.h \
futures/detail/FSM.h \ futures/detail/FSM.h \
futures/detail/Types.h \ futures/detail/Types.h \
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <folly/Optional.h> #include <folly/Optional.h>
#include <folly/executors/InlineExecutor.h> #include <folly/executors/InlineExecutor.h>
#include <folly/executors/QueuedImmediateExecutor.h> #include <folly/executors/QueuedImmediateExecutor.h>
#include <folly/futures/Timekeeper.h>
#include <folly/futures/detail/Core.h> #include <folly/futures/detail/Core.h>
#include <folly/synchronization/Baton.h> #include <folly/synchronization/Baton.h>
...@@ -1988,6 +1987,17 @@ std::vector<Future<Result>> map(It first, It last, F func) { ...@@ -1988,6 +1987,17 @@ std::vector<Future<Result>> map(It first, It last, F func) {
} }
} // namespace futures } // namespace futures
template <class Clock>
Future<Unit> Timekeeper::at(std::chrono::time_point<Clock> when) {
auto now = Clock::now();
if (when <= now) {
return makeFuture();
}
return after(std::chrono::duration_cast<Duration>(when - now));
}
// Instantiate the most common Future types to save compile time // Instantiate the most common Future types to save compile time
extern template class Future<Unit>; extern template class Future<Unit>;
extern template class Future<bool>; extern template class Future<bool>;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <folly/Portability.h> #include <folly/Portability.h>
#include <folly/ScopeGuard.h> #include <folly/ScopeGuard.h>
#include <folly/Try.h> #include <folly/Try.h>
#include <folly/Unit.h>
#include <folly/Utility.h> #include <folly/Utility.h>
#include <folly/executors/DrivableExecutor.h> #include <folly/executors/DrivableExecutor.h>
#include <folly/executors/TimedDrivableExecutor.h> #include <folly/executors/TimedDrivableExecutor.h>
...@@ -952,6 +953,59 @@ class Future : private futures::detail::FutureBase<T> { ...@@ -952,6 +953,59 @@ class Future : private futures::detail::FutureBase<T> {
Future<FT>& f); Future<FT>& f);
}; };
/// A Timekeeper handles the details of keeping time and fulfilling delay
/// promises. The returned Future<Unit> will either complete after the
/// elapsed time, or in the event of some kind of exceptional error may hold
/// an exception. These Futures respond to cancellation. If you use a lot of
/// Delays and many of them ultimately are unneeded (as would be the case for
/// Delays that are used to trigger timeouts of async operations), then you
/// can and should cancel them to reclaim resources.
///
/// Users will typically get one of these via Future::sleep(Duration) or
/// use them implicitly behind the scenes by passing a timeout to some Future
/// operation.
///
/// Although we don't formally alias Delay = Future<Unit>,
/// that's an appropriate term for it. People will probably also call these
/// Timeouts, and that's ok I guess, but that term is so overloaded I thought
/// it made sense to introduce a cleaner term.
///
/// Remember that Duration is a std::chrono duration (millisecond resolution
/// at the time of writing). When writing code that uses specific durations,
/// prefer using the explicit std::chrono type, e.g. std::chrono::milliseconds
/// over Duration. This makes the code more legible and means you won't be
/// unpleasantly surprised if we redefine Duration to microseconds, or
/// something.
///
/// timekeeper.after(std::chrono::duration_cast<Duration>(
/// someNanoseconds))
class Timekeeper {
public:
virtual ~Timekeeper() = default;
/// Returns a future that will complete after the given duration with the
/// elapsed time. Exceptional errors can happen but they must be
/// exceptional. Use the steady (monotonic) clock.
///
/// You may cancel this Future to reclaim resources.
///
/// This future probably completes on the timer thread. You should almost
/// certainly follow it with a via() call or the accuracy of other timers
/// will suffer.
virtual Future<Unit> after(Duration) = 0;
/// Returns a future that will complete at the requested time.
///
/// You may cancel this Future to reclaim resources.
///
/// NB This is sugar for `after(when - now)`, so while you are welcome to
/// use a std::chrono::system_clock::time_point it will not track changes to
/// the system clock but rather execute that many milliseconds in the future
/// according to the steady clock.
template <class Clock>
Future<Unit> at(std::chrono::time_point<Clock> when);
};
} // namespace folly } // namespace folly
#if FOLLY_HAS_COROUTINES #if FOLLY_HAS_COROUTINES
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#pragma once #pragma once
#include <folly/futures/Future.h> #include <folly/futures/Future.h>
#include <folly/futures/Timekeeper.h>
#include <folly/io/async/EventBase.h> #include <folly/io/async/EventBase.h>
#include <folly/io/async/HHWheelTimer.h> #include <folly/io/async/HHWheelTimer.h>
#include <thread> #include <thread>
......
/*
* Copyright 2014-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <folly/Unit.h>
#include <folly/futures/detail/Types.h>
namespace folly {
template <class> class Future;
/// A Timekeeper handles the details of keeping time and fulfilling delay
/// promises. The returned Future<Unit> will either complete after the
/// elapsed time, or in the event of some kind of exceptional error may hold
/// an exception. These Futures respond to cancellation. If you use a lot of
/// Delays and many of them ultimately are unneeded (as would be the case for
/// Delays that are used to trigger timeouts of async operations), then you
/// can and should cancel them to reclaim resources.
///
/// Users will typically get one of these via Future::sleep(Duration) or
/// use them implicitly behind the scenes by passing a timeout to some Future
/// operation.
///
/// Although we don't formally alias Delay = Future<Unit>,
/// that's an appropriate term for it. People will probably also call these
/// Timeouts, and that's ok I guess, but that term is so overloaded I thought
/// it made sense to introduce a cleaner term.
///
/// Remember that Duration is a std::chrono duration (millisecond resolution
/// at the time of writing). When writing code that uses specific durations,
/// prefer using the explicit std::chrono type, e.g. std::chrono::milliseconds
/// over Duration. This makes the code more legible and means you won't be
/// unpleasantly surprised if we redefine Duration to microseconds, or
/// something.
///
/// timekeeper.after(std::chrono::duration_cast<Duration>(
/// someNanoseconds))
class Timekeeper {
public:
virtual ~Timekeeper() = default;
/// Returns a future that will complete after the given duration with the
/// elapsed time. Exceptional errors can happen but they must be
/// exceptional. Use the steady (monotonic) clock.
///
/// You may cancel this Future to reclaim resources.
///
/// This future probably completes on the timer thread. You should almost
/// certainly follow it with a via() call or the accuracy of other timers
/// will suffer.
virtual Future<Unit> after(Duration) = 0;
/// Returns a future that will complete at the requested time.
///
/// You may cancel this Future to reclaim resources.
///
/// NB This is sugar for `after(when - now)`, so while you are welcome to
/// use a std::chrono::system_clock::time_point it will not track changes to
/// the system clock but rather execute that many milliseconds in the future
/// according to the steady clock.
template <class Clock>
Future<Unit> at(std::chrono::time_point<Clock> when);
};
} // namespace folly
// now get those definitions
#include <folly/futures/Future.h>
// finally we can use Future
namespace folly {
template <class Clock>
Future<Unit> Timekeeper::at(std::chrono::time_point<Clock> when) {
auto now = Clock::now();
if (when <= now) {
return makeFuture();
}
return after(std::chrono::duration_cast<Duration>(when - now));
}
} // namespace folly
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
#include <folly/futures/Timekeeper.h>
#include <folly/Singleton.h> #include <folly/Singleton.h>
#include <folly/futures/Future.h>
#include <folly/futures/ThreadWheelTimekeeper.h> #include <folly/futures/ThreadWheelTimekeeper.h>
#include <folly/portability/GTest.h> #include <folly/portability/GTest.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment