#pragma once
#include <algorithm>
#include <atomic>
#include <cassert>
#include <chrono>
#include <thread>
#include <type_traits>
#include <utility>
#include <folly/Optional.h>
#include <folly/Traits.h>
#include <folly/container/Foreach.h>
#include <folly/detail/AsyncTrace.h>
#include <folly/executors/ExecutorWithPriority.h>
#include <folly/executors/GlobalExecutor.h>
#include <folly/executors/InlineExecutor.h>
#include <folly/executors/QueuedImmediateExecutor.h>
#include <folly/futures/detail/Core.h>
#include <folly/lang/Pretty.h>
namespace folly {
class Timekeeper;
namespace futures {
namespace detail {
FutureBatonType;
}
}
namespace detail {
struct TimekeeperSingletonTag { … };
std::shared_ptr<Timekeeper> getTimekeeperSingleton();
}
namespace futures {
namespace detail {
template <typename T>
struct InvokeResultWrapperBase { … };
template <typename T>
struct InvokeResultWrapper : InvokeResultWrapperBase<Try<T>> { … };
InvokeResultWrapper<Try<T>>;
InvokeResultWrapper<SemiFuture<T>>;
InvokeResultWrapper<Future<T>>;
template <>
struct InvokeResultWrapper<void> : InvokeResultWrapperBase<Try<Unit>> { … };
template <typename T, typename F>
auto wrapInvoke(folly::Try<T>&& t, F&& f) { … }
template <typename T, typename F>
class CoreCallbackState { … };
template <typename T, typename F>
auto makeCoreCallbackState(Promise<T>&& p, F&& f) noexcept(
noexcept(CoreCallbackState<T, F>(std::move(p), static_cast<F&&>(f)))) { … }
template <typename T, typename R, typename... Args>
auto makeCoreCallbackState(Promise<T>&& p, R (&f)(Args...)) noexcept { … }
template <class T>
FutureBase<T>::FutureBase(SemiFuture<T>&& other) noexcept : … { … }
template <class T>
FutureBase<T>::FutureBase(Future<T>&& other) noexcept : … { … }
template <class T>
template <class T2, typename>
FutureBase<T>::FutureBase(T2&& val)
: core_(Core::make(Try<T>(static_cast<T2&&>(val)))) { … }
template <class T>
template <typename T2>
FutureBase<T>::FutureBase(
typename std::enable_if<std::is_same<Unit, T2>::value>::type*)
: core_(Core::make(Try<T>(T()))) { … }
template <class T>
void FutureBase<T>::assign(FutureBase<T>&& other) noexcept { … }
template <class T>
FutureBase<T>::~FutureBase() { … }
template <class T>
T& FutureBase<T>::value() & { … }
template <class T>
T const& FutureBase<T>::value() const& { … }
template <class T>
T&& FutureBase<T>::value() && { … }
template <class T>
T const&& FutureBase<T>::value() const&& { … }
template <class T>
Try<T>& FutureBase<T>::result() & { … }
template <class T>
Try<T> const& FutureBase<T>::result() const& { … }
template <class T>
Try<T>&& FutureBase<T>::result() && { … }
template <class T>
Try<T> const&& FutureBase<T>::result() const&& { … }
template <class T>
bool FutureBase<T>::isReady() const { … }
template <class T>
bool FutureBase<T>::hasValue() const { … }
template <class T>
bool FutureBase<T>::hasException() const { … }
template <class T>
void FutureBase<T>::detach() { … }
template <class T>
void FutureBase<T>::throwIfInvalid() const { … }
template <class T>
void FutureBase<T>::throwIfContinued() const { … }
template <class T>
Optional<Try<T>> FutureBase<T>::poll() { … }
template <class T>
void FutureBase<T>::raise(exception_wrapper exception) { … }
template <class T>
template <class F>
void FutureBase<T>::setCallback_(
F&& func,
std::shared_ptr<folly::RequestContext>&& context,
futures::detail::InlineContinuation allowInline) { … }
template <class T>
template <class F>
void FutureBase<T>::setCallback_(
F&& func, futures::detail::InlineContinuation allowInline) { … }
template <class T>
FutureBase<T>::FutureBase(futures::detail::EmptyConstruct) noexcept
: … { … }
namespace detail_msvc_15_7_workaround {
IfArgsSizeIs;
template <typename R, typename State, typename T, IfArgsSizeIs<R, 0> = 0>
decltype(auto) invoke(
R, State& state, Executor::KeepAlive<>&&, Try<T>&& ) { … }
template <typename R, typename State, typename T, IfArgsSizeIs<R, 2> = 0>
decltype(auto) invoke(R, State& state, Executor::KeepAlive<>&& ka, Try<T>&& t) { … }
template <typename R, typename State, typename T, IfArgsSizeIs<R, 0> = 0>
decltype(auto) tryInvoke(
R, State& state, Executor::KeepAlive<>&&, Try<T>&& ) { … }
template <typename R, typename State, typename T, IfArgsSizeIs<R, 2> = 0>
decltype(auto) tryInvoke(
R, State& state, Executor::KeepAlive<>&& ka, Try<T>&& t) { … }
}
class FutureBaseHelper { … };
template <class T>
template <typename F, typename R>
typename std::enable_if<
!R::ReturnsFuture::value,
Future<typename R::value_type>>::type
FutureBase<T>::thenImplementation(
F&& func, R, futures::detail::InlineContinuation allowInline) { … }
template <class T>
Future<T> chainExecutor(Executor::KeepAlive<>, Future<T>&& f) { … }
template <class T>
Future<T> chainExecutor(Executor::KeepAlive<> e, SemiFuture<T>&& f) { … }
template <class T>
template <typename F, typename R>
typename std::enable_if<
R::ReturnsFuture::value,
Future<typename R::value_type>>::type
FutureBase<T>::thenImplementation(
F&& func, R, futures::detail::InlineContinuation allowInline) { … }
class WaitExecutor final : public folly::Executor { … };
struct WindowFakeVector { … };
}
}
template <class T>
SemiFuture<typename std::decay<T>::type> makeSemiFuture(T&& t) { … }
template <class F>
typename std::enable_if<
isFutureOrSemiFuture<invoke_result_t<F>>::value,
SemiFuture<typename invoke_result_t<F>::value_type>>::type
makeSemiFutureWith(F&& func) { … }
template <class F>
typename std::enable_if<
!(isFutureOrSemiFuture<invoke_result_t<F>>::value),
SemiFuture<lift_unit_t<invoke_result_t<F>>>>::type
makeSemiFutureWith(F&& func) { … }
template <class T>
SemiFuture<T> makeSemiFuture(std::exception_ptr const& e) { … }
template <class T>
SemiFuture<T> makeSemiFuture(exception_wrapper ew) { … }
template <class T, class E>
typename std::
enable_if<std::is_base_of<std::exception, E>::value, SemiFuture<T>>::type
makeSemiFuture(E const& e) { … }
template <class T>
SemiFuture<T> makeSemiFuture(Try<T> t) { … }
inline SemiFuture<Unit> makeSemiFuture() { … }
template <class T>
SemiFuture<T> SemiFuture<T>::makeEmpty() { … }
template <class T>
futures::detail::DeferredWrapper SemiFuture<T>::stealDeferredExecutor() { … }
template <class T>
void SemiFuture<T>::releaseDeferredExecutor(Core* core) { … }
template <class T>
SemiFuture<T>::~SemiFuture() { … }
template <class T>
SemiFuture<T>::SemiFuture(SemiFuture<T>&& other) noexcept
: … { … }
template <class T>
SemiFuture<T>::SemiFuture(Future<T>&& other) noexcept
: … { … }
template <class T>
SemiFuture<T>& SemiFuture<T>::operator=(SemiFuture<T>&& other) noexcept { … }
template <class T>
SemiFuture<T>& SemiFuture<T>::operator=(Future<T>&& other) noexcept { … }
template <class T>
Future<T> SemiFuture<T>::via(Executor::KeepAlive<> executor) && { … }
template <class T>
Future<T> SemiFuture<T>::viaInlineUnsafe(Executor::KeepAlive<> executor) && { … }
template <class T>
Future<T> SemiFuture<T>::via(
Executor::KeepAlive<> executor, int8_t priority) && { … }
template <class T>
Future<T> SemiFuture<T>::toUnsafeFuture() && { … }
template <class T>
template <typename F>
SemiFuture<typename futures::detail::tryCallableResult<T, F>::value_type>
SemiFuture<T>::defer(F&& func) && { … }
template <class T>
template <typename F>
SemiFuture<
typename futures::detail::tryExecutorCallableResult<T, F>::value_type>
SemiFuture<T>::deferExTry(F&& func) && { … }
template <class T>
template <typename F>
SemiFuture<typename futures::detail::valueCallableResult<T, F>::value_type>
SemiFuture<T>::deferValue(F&& func) && { … }
template <class T>
template <typename F>
SemiFuture<
typename futures::detail::valueExecutorCallableResult<T, F>::value_type>
SemiFuture<T>::deferExValue(F&& func) && { … }
template <class T>
template <class ExceptionType, class F>
SemiFuture<T> SemiFuture<T>::deferError(tag_t<ExceptionType>, F&& func) && { … }
template <class T>
template <class F>
SemiFuture<T> SemiFuture<T>::deferError(F&& func) && { … }
template <class T>
template <class F>
SemiFuture<T> SemiFuture<T>::deferEnsure(F&& func) && { … }
template <class T>
SemiFuture<Unit> SemiFuture<T>::unit() && { … }
template <typename T>
SemiFuture<T> SemiFuture<T>::delayed(HighResDuration dur, Timekeeper* tk) && { … }
template <class T>
Future<T> Future<T>::makeEmpty() { … }
template <class T>
Future<T>::Future(Future<T>&& other) noexcept
: … { … }
template <class T>
Future<T>& Future<T>::operator=(Future<T>&& other) noexcept { … }
template <class T>
template <class F>
typename std::
enable_if<isFuture<F>::value, Future<typename isFuture<T>::Inner>>::type
Future<T>::unwrap() && { … }
template <class T>
Future<T> Future<T>::via(Executor::KeepAlive<> executor) && { … }
template <class T>
Future<T> Future<T>::via(Executor::KeepAlive<> executor, int8_t priority) && { … }
template <class T>
Future<T> Future<T>::via(Executor::KeepAlive<> executor) & { … }
template <class T>
Future<T> Future<T>::via(Executor::KeepAlive<> executor, int8_t priority) & { … }
template <typename T>
template <typename R, typename Caller, typename... Args>
Future<typename isFuture<R>::Inner> Future<T>::then(
R (Caller::*func)(Args...), Caller* instance) && { … }
template <class T>
template <typename F>
Future<typename futures::detail::tryCallableResult<T, F>::value_type>
Future<T>::thenTry(F&& func) && { … }
template <class T>
template <typename F>
Future<typename futures::detail::tryCallableResult<T, F>::value_type>
Future<T>::thenTryInline(F&& func) && { … }
template <class T>
template <typename F>
Future<typename futures::detail::tryExecutorCallableResult<T, F>::value_type>
Future<T>::thenExTry(F&& func) && { … }
template <class T>
template <typename F>
Future<typename futures::detail::tryExecutorCallableResult<T, F>::value_type>
Future<T>::thenExTryInline(F&& func) && { … }
template <class T>
template <typename F>
Future<typename futures::detail::valueCallableResult<T, F>::value_type>
Future<T>::thenValue(F&& func) && { … }
template <class T>
template <typename F>
Future<typename futures::detail::valueCallableResult<T, F>::value_type>
Future<T>::thenValueInline(F&& func) && { … }
template <class T>
template <typename F>
Future<typename futures::detail::valueExecutorCallableResult<T, F>::value_type>
Future<T>::thenExValue(F&& func) && { … }
template <class T>
template <typename F>
Future<typename futures::detail::valueExecutorCallableResult<T, F>::value_type>
Future<T>::thenExValueInline(F&& func) && { … }
template <class T>
template <class ExceptionType, class F>
typename std::enable_if<
isFutureOrSemiFuture<invoke_result_t<F, ExceptionType>>::value,
Future<T>>::type
Future<T>::thenError(tag_t<ExceptionType>, F&& func) && { … }
template <class T>
template <class ExceptionType, class F>
Future<T> Future<T>::thenErrorInline(tag_t<ExceptionType>, F&& func) && { … }
template <class T>
template <class ExceptionType, class F>
typename std::enable_if<
isFutureOrSemiFuture<invoke_result_t<F, ExceptionType>>::value,
Future<T>>::type
Future<T>::thenErrorImpl(
tag_t<ExceptionType>,
F&& func,
futures::detail::InlineContinuation allowInline) && { … }
template <class T>
template <class ExceptionType, class F>
typename std::enable_if<
!isFutureOrSemiFuture<invoke_result_t<F, ExceptionType>>::value,
Future<T>>::type
Future<T>::thenError(tag_t<ExceptionType>, F&& func) && { … }
template <class T>
template <class ExceptionType, class F>
typename std::enable_if<
!isFutureOrSemiFuture<invoke_result_t<F, ExceptionType>>::value,
Future<T>>::type
Future<T>::thenErrorImpl(
tag_t<ExceptionType>,
F&& func,
futures::detail::InlineContinuation allowInline) && { … }
template <class T>
template <class F>
typename std::enable_if<
isFutureOrSemiFuture<invoke_result_t<F, exception_wrapper>>::value,
Future<T>>::type
Future<T>::thenError(F&& func) && { … }
template <class T>
template <class F>
typename std::enable_if<
!isFutureOrSemiFuture<invoke_result_t<F, exception_wrapper>>::value,
Future<T>>::type
Future<T>::thenError(F&& func) && { … }
template <class T>
template <class F>
Future<T> Future<T>::thenErrorInline(F&& func) && { … }
template <class T>
template <class F>
typename std::enable_if<
isFutureOrSemiFuture<invoke_result_t<F, exception_wrapper>>::value,
Future<T>>::type
Future<T>::thenErrorImpl(
F&& func, futures::detail::InlineContinuation allowInline) && { … }
template <class T>
template <class F>
typename std::enable_if<
!isFutureOrSemiFuture<invoke_result_t<F, exception_wrapper>>::value,
Future<T>>::type
Future<T>::thenErrorImpl(
F&& func, futures::detail::InlineContinuation allowInline) && { … }
template <class T>
Future<Unit> Future<T>::then() && { … }
template <class T>
template <class F>
Future<T> Future<T>::ensure(F&& func) && { … }
template <class T>
template <class F>
Future<T> Future<T>::ensureInline(F&& func) && { … }
template <class T>
template <class F>
Future<T> Future<T>::onTimeout(
HighResDuration dur, F&& func, Timekeeper* tk) && { … }
template <class Func>
auto via(Executor::KeepAlive<> x, Func&& func)
-> Future<typename isFutureOrSemiFuture<
decltype(static_cast<Func&&>(func)())>::Inner> { … }
template <class T>
Future<typename std::decay<T>::type> makeFuture(T&& t) { … }
inline Future<Unit> makeFuture() { … }
template <class F>
typename std::
enable_if<isFuture<invoke_result_t<F>>::value, invoke_result_t<F>>::type
makeFutureWith(F&& func) { … }
template <class F>
typename std::enable_if<
!(isFuture<invoke_result_t<F>>::value),
Future<lift_unit_t<invoke_result_t<F>>>>::type
makeFutureWith(F&& func) { … }
template <class T>
Future<T> makeFuture(std::exception_ptr const& e) { … }
template <class T>
Future<T> makeFuture(exception_wrapper ew) { … }
template <class T, class E>
typename std::enable_if<std::is_base_of<std::exception, E>::value, Future<T>>::
type
makeFuture(E const& e) { … }
template <class T>
Future<T> makeFuture(Try<T> t) { … }
Future<Unit> via(Executor::KeepAlive<> executor) { … }
Future<Unit> via(Executor::KeepAlive<> executor, int8_t priority) { … }
namespace futures {
namespace detail {
template <typename V, typename... Fs, std::size_t... Is>
FOLLY_ERASE void foreach_(std::index_sequence<Is...>, V&& v, Fs&&... fs) { … }
template <typename V, typename... Fs>
FOLLY_ERASE void foreach(V&& v, Fs&&... fs) { … }
template <typename T>
futures::detail::DeferredExecutor* getDeferredExecutor(SemiFuture<T>& future) { … }
template <typename T>
futures::detail::DeferredWrapper stealDeferredExecutor(SemiFuture<T>& future) { … }
template <typename T>
futures::detail::DeferredWrapper stealDeferredExecutor(Future<T>&) { … }
template <typename... Ts>
void stealDeferredExecutorsVariadic(
std::vector<futures::detail::DeferredWrapper>& executors, Ts&... ts) { … }
template <class InputIterator>
void stealDeferredExecutors(
std::vector<futures::detail::DeferredWrapper>& executors,
InputIterator first,
InputIterator last) { … }
}
}
template <typename... Fs>
SemiFuture<std::tuple<Try<typename remove_cvref_t<Fs>::value_type>...>>
collectAll(Fs&&... fs) { … }
template <typename... Fs>
Future<std::tuple<Try<typename remove_cvref_t<Fs>::value_type>...>>
collectAllUnsafe(Fs&&... fs) { … }
template <class InputIterator>
SemiFuture<std::vector<
Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
collectAll(InputIterator first, InputIterator last) { … }
template <class InputIterator>
Future<std::vector<
Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
collectAllUnsafe(InputIterator first, InputIterator last) { … }
template <class InputIterator>
SemiFuture<std::vector<
typename std::iterator_traits<InputIterator>::value_type::value_type>>
collect(InputIterator first, InputIterator last) { … }
template <class InputIterator>
Future<std::vector<
typename std::iterator_traits<InputIterator>::value_type::value_type>>
collectUnsafe(InputIterator first, InputIterator last) { … }
template <typename... Fs>
SemiFuture<std::tuple<typename remove_cvref_t<Fs>::value_type...>> collect(
Fs&&... fs) { … }
template <typename... Fs>
Future<std::tuple<typename remove_cvref_t<Fs>::value_type...>> collectUnsafe(
Fs&&... fs) { … }
template <class InputIterator>
SemiFuture<std::pair<
size_t,
Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
collectAny(InputIterator first, InputIterator last) { … }
template <class InputIterator>
SemiFuture<std::pair<
size_t,
typename std::iterator_traits<InputIterator>::value_type::value_type>>
collectAnyWithoutException(InputIterator first, InputIterator last) { … }
template <class InputIterator>
SemiFuture<std::vector<std::pair<
size_t,
Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>>
collectN(InputIterator first, InputIterator last, size_t n) { … }
template <class It, class T, class F>
Future<T> reduce(It first, It last, T&& initial, F&& func) { … }
template <class Collection, class F, class ItT, class Result>
std::vector<Future<Result>> window(Collection input, F func, size_t n) { … }
template <class F>
auto window(size_t times, F func, size_t n)
-> std::vector<invoke_result_t<F, size_t>> { … }
template <class Collection, class F, class ItT, class Result>
std::vector<Future<Result>> window(
Executor::KeepAlive<> executor, Collection input, F func, size_t n) { … }
template <class T>
template <class In, class F>
Future<In> Future<T>::reduce(In&& initial, F&& func) && { … }
template <class It, class T, class F>
SemiFuture<T> unorderedReduceSemiFuture(It first, It last, T initial, F func) { … }
template <class It, class T, class F>
Future<T> unorderedReduce(It first, It last, T initial, F func) { … }
template <class T>
Future<T> Future<T>::within(HighResDuration dur, Timekeeper* tk) && { … }
template <class T>
template <class E>
Future<T> Future<T>::within(HighResDuration dur, E e, Timekeeper* tk) && { … }
namespace futures {
namespace detail {
struct WithinInterruptHandler { … };
struct WithinContextBase { … };
struct WithinAfterFutureCallback { … };
}
}
template <class T>
template <typename E>
SemiFuture<T> SemiFuture<T>::within(
HighResDuration dur, E e, Timekeeper* tk) && { … }
template <class T>
Future<T> Future<T>::delayed(HighResDuration dur, Timekeeper* tk) && { … }
namespace futures {
namespace detail {
template <class FutureType, typename T = typename FutureType::value_type>
void waitImpl(FutureType& f) { … }
template <class T>
Future<T> convertFuture(SemiFuture<T>&& sf, const Future<T>& f) { … }
template <class T>
SemiFuture<T> convertFuture(SemiFuture<T>&& sf, const SemiFuture<T>&) { … }
template <class FutureType, typename T = typename FutureType::value_type>
void waitImpl(FutureType& f, HighResDuration dur) { … }
template <class T>
void waitViaImpl(Future<T>& f, DrivableExecutor* e) { … }
template <class T, typename Rep, typename Period>
void waitViaImpl(
Future<T>& f,
TimedDrivableExecutor* e,
const std::chrono::duration<Rep, Period>& timeout) { … }
}
}
template <class T>
SemiFuture<T>& SemiFuture<T>::wait() & { … }
template <class T>
SemiFuture<T>&& SemiFuture<T>::wait() && { … }
template <class T>
SemiFuture<T>& SemiFuture<T>::wait(HighResDuration dur) & { … }
template <class T>
bool SemiFuture<T>::wait(HighResDuration dur) && { … }
template <class T>
T SemiFuture<T>::get() && { … }
template <class T>
T SemiFuture<T>::get(HighResDuration dur) && { … }
template <class T>
Try<T> SemiFuture<T>::getTry() && { … }
template <class T>
Try<T> SemiFuture<T>::getTry(HighResDuration dur) && { … }
template <class T>
Future<T>& Future<T>::wait() & { … }
template <class T>
Future<T>&& Future<T>::wait() && { … }
template <class T>
Future<T>& Future<T>::wait(HighResDuration dur) & { … }
template <class T>
Future<T>&& Future<T>::wait(HighResDuration dur) && { … }
template <class T>
Future<T>& Future<T>::waitVia(DrivableExecutor* e) & { … }
template <class T>
Future<T>&& Future<T>::waitVia(DrivableExecutor* e) && { … }
template <class T>
Future<T>& Future<T>::waitVia(TimedDrivableExecutor* e, HighResDuration dur) & { … }
template <class T>
Future<T>&& Future<T>::waitVia(
TimedDrivableExecutor* e, HighResDuration dur) && { … }
template <class T>
T Future<T>::get() && { … }
template <class T>
T Future<T>::get(HighResDuration dur) && { … }
template <class T>
Try<T> Future<T>::getTry() && { … }
template <class T>
Try<T> Future<T>::getTry(HighResDuration dur) && { … }
template <class T>
T Future<T>::getVia(DrivableExecutor* e) && { … }
template <class T>
T Future<T>::getVia(TimedDrivableExecutor* e, HighResDuration dur) && { … }
template <class T>
Try<T> Future<T>::getTryVia(DrivableExecutor* e) && { … }
template <class T>
Try<T> Future<T>::getTryVia(TimedDrivableExecutor* e, HighResDuration dur) && { … }
namespace futures {
namespace detail {
template <class T>
struct TryEquals { … };
}
}
template <class T>
Future<bool> Future<T>::willEqual(Future<T>& f) { … }
template <class T>
template <class F>
Future<T> Future<T>::filter(F&& predicate) && { … }
template <class F>
auto when(bool p, F&& thunk) -> decltype(static_cast<F&&>(thunk)().unit()) { … }
template <class P, class F>
typename std::
enable_if<isSemiFuture<invoke_result_t<F>>::value, SemiFuture<Unit>>::type
whileDo(P&& predicate, F&& thunk) { … }
template <class P, class F>
typename std::enable_if<isFuture<invoke_result_t<F>>::value, Future<Unit>>::type
whileDo(P&& predicate, F&& thunk) { … }
template <class F>
auto times(const int n, F&& thunk) { … }
namespace futures {
template <class It, class F, class ItT, class Tag, class Result>
std::vector<Future<Result>> mapValue(It first, It last, F func) { … }
template <class It, class F, class ItT, class Tag, class Result>
std::vector<Future<Result>> mapTry(It first, It last, F func, int) { … }
template <class It, class F, class ItT, class Tag, class Result>
std::vector<Future<Result>> mapValue(
Executor& exec, It first, It last, F func) { … }
template <class It, class F, class ItT, class Tag, class Result>
std::vector<Future<Result>> mapTry(
Executor& exec, It first, It last, F func, int) { … }
template <typename F, class Ensure>
auto ensure(F&& f, Ensure&& ensure) { … }
template <class T>
void detachOn(folly::Executor::KeepAlive<> exec, folly::SemiFuture<T>&& fut) { … }
template <class T>
void detachOnGlobalCPUExecutor(folly::SemiFuture<T>&& fut) { … }
template <class T>
void maybeDetachOnGlobalExecutorAfter(
HighResDuration dur, folly::SemiFuture<T>&& fut) { … }
template <class T>
void detachWithoutExecutor(folly::SemiFuture<T>&& fut) { … }
}
template <class Clock>
SemiFuture<Unit> Timekeeper::at(std::chrono::time_point<Clock> when) { … }
#if FOLLY_USE_EXTERN_FUTURE_UNIT
namespace futures {
namespace detail {
extern template class FutureBase<Unit>;
}
}
extern template class Future<Unit>;
extern template class SemiFuture<Unit>;
#endif
}