class Timekeeper;
+namespace futures {
namespace detail {
#if FOLLY_FUTURE_USING_FIBER
typedef folly::fibers::Baton FutureBatonType;
#else
typedef folly::Baton<> FutureBatonType;
#endif
-}
+} // namespace detail
+} // namespace futures
namespace detail {
std::shared_ptr<Timekeeper> getTimekeeperSingleton();
+} // namespace detail
+namespace futures {
+namespace detail {
// Guarantees that the stored functor is destructed before the stored promise
// may be fulfilled. Assumes the stored functor to be noexcept-destructible.
template <typename T, typename F>
return CoreCallbackState<T, _t<std::decay<F>>>(
std::move(p), std::forward<F>(f));
}
-}
+} // namespace detail
+} // namespace futures
template <class T>
Future<T> Future<T>::makeEmpty() {
- return Future<T>(detail::EmptyConstruct{});
+ return Future<T>(futures::detail::EmptyConstruct{});
}
template <class T>
template <class T>
template <class T2, typename>
Future<T>::Future(T2&& val)
- : core_(new detail::Core<T>(Try<T>(std::forward<T2>(val)))) {}
+ : core_(new futures::detail::Core<T>(Try<T>(std::forward<T2>(val)))) {}
template <class T>
template <typename T2>
Future<T>::Future(typename std::enable_if<std::is_same<Unit, T2>::value>::type*)
- : core_(new detail::Core<T>(Try<T>(T()))) {}
+ : core_(new futures::detail::Core<T>(Try<T>(T()))) {}
template <class T>
template <
typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::
type>
Future<T>::Future(in_place_t, Args&&... args)
- : core_(new detail::Core<T>(in_place, std::forward<Args>(args)...)) {}
+ : core_(
+ new futures::detail::Core<T>(in_place, std::forward<Args>(args)...)) {
+}
template <class T>
Future<T>::~Future() {
template <class T>
template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<!R::ReturnsFuture::value, typename R::Return>::type
-Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) {
+Future<T>::thenImplementation(
+ F&& func,
+ futures::detail::argResult<isTry, F, Args...>) {
static_assert(sizeof...(Args) <= 1, "Then must take zero/one argument");
typedef typename R::ReturnsFuture::Inner B;
persist beyond the callback, if it gets moved), and so it is an
optimization to just make it shared from the get-go.
- Two subtle but important points about this design. detail::Core has no
- back pointers to Future or Promise, so if Future or Promise get moved
- (and they will be moved in performant code) we don't have to do
+ Two subtle but important points about this design. futures::detail::Core
+ has no back pointers to Future or Promise, so if Future or Promise get
+ moved (and they will be moved in performant code) we don't have to do
anything fancy. And because we store the continuation in the
- detail::Core, not in the Future, we can execute the continuation even
- after the Future has gone out of scope. This is an intentional design
+ futures::detail::Core, not in the Future, we can execute the continuation
+ even after the Future has gone out of scope. This is an intentional design
decision. It is likely we will want to be able to cancel a continuation
in some circumstances, but I think it should be explicit not implicit
in the destruction of the Future used to create it.
*/
setCallback_(
- [state = detail::makeCoreCallbackState(
+ [state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (!isTry && t.hasException()) {
state.setException(std::move(t.exception()));
template <class T>
template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<R::ReturnsFuture::value, typename R::Return>::type
-Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) {
+Future<T>::thenImplementation(
+ F&& func,
+ futures::detail::argResult<isTry, F, Args...>) {
static_assert(sizeof...(Args) <= 1, "Then must take zero/one argument");
typedef typename R::ReturnsFuture::Inner B;
f.core_->setExecutorNoLock(getExecutor());
setCallback_(
- [state = detail::makeCoreCallbackState(
+ [state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (!isTry && t.hasException()) {
state.setException(std::move(t.exception()));
template <typename R, typename Caller, typename... Args>
Future<typename isFuture<R>::Inner>
Future<T>::then(R(Caller::*func)(Args...), Caller *instance) {
- typedef typename std::remove_cv<
- typename std::remove_reference<
- typename detail::ArgType<Args...>::FirstArg>::type>::type FirstArg;
+ typedef typename std::remove_cv<typename std::remove_reference<
+ typename futures::detail::ArgType<Args...>::FirstArg>::type>::type
+ FirstArg;
return then([instance, func](Try<T>&& t){
return (instance->*func)(t.template get<isTry<FirstArg>::value, Args>()...);
});
template <class T>
template <class F>
typename std::enable_if<
- !detail::callableWith<F, exception_wrapper>::value &&
- !detail::Extract<F>::ReturnsFuture::value,
- Future<T>>::type
+ !futures::detail::callableWith<F, exception_wrapper>::value &&
+ !futures::detail::Extract<F>::ReturnsFuture::value,
+ Future<T>>::type
Future<T>::onError(F&& func) {
- typedef std::remove_reference_t<typename detail::Extract<F>::FirstArg> Exn;
+ typedef std::remove_reference_t<
+ typename futures::detail::Extract<F>::FirstArg>
+ Exn;
static_assert(
- std::is_same<typename detail::Extract<F>::RawReturn, T>::value,
+ std::is_same<typename futures::detail::Extract<F>::RawReturn, T>::value,
"Return type of onError callback must be T or Future<T>");
Promise<T> p;
auto f = p.getFuture();
setCallback_(
- [state = detail::makeCoreCallbackState(
+ [state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (auto e = t.template tryGetExceptionObject<Exn>()) {
state.setTry(makeTryWith([&] { return state.invoke(*e); }));
template <class T>
template <class F>
typename std::enable_if<
- !detail::callableWith<F, exception_wrapper>::value &&
- detail::Extract<F>::ReturnsFuture::value,
- Future<T>>::type
+ !futures::detail::callableWith<F, exception_wrapper>::value &&
+ futures::detail::Extract<F>::ReturnsFuture::value,
+ Future<T>>::type
Future<T>::onError(F&& func) {
static_assert(
- std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
+ std::is_same<typename futures::detail::Extract<F>::Return, Future<T>>::
+ value,
"Return type of onError callback must be T or Future<T>");
- typedef std::remove_reference_t<typename detail::Extract<F>::FirstArg> Exn;
+ typedef std::remove_reference_t<
+ typename futures::detail::Extract<F>::FirstArg>
+ Exn;
Promise<T> p;
auto f = p.getFuture();
setCallback_(
- [state = detail::makeCoreCallbackState(
+ [state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (auto e = t.template tryGetExceptionObject<Exn>()) {
auto tf2 = state.tryInvoke(*e);
template <class T>
template <class F>
-typename std::enable_if<detail::callableWith<F, exception_wrapper>::value &&
- detail::Extract<F>::ReturnsFuture::value,
- Future<T>>::type
+typename std::enable_if<
+ futures::detail::callableWith<F, exception_wrapper>::value &&
+ futures::detail::Extract<F>::ReturnsFuture::value,
+ Future<T>>::type
Future<T>::onError(F&& func) {
static_assert(
- std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
+ std::is_same<typename futures::detail::Extract<F>::Return, Future<T>>::
+ value,
"Return type of onError callback must be T or Future<T>");
Promise<T> p;
auto f = p.getFuture();
setCallback_(
- [state = detail::makeCoreCallbackState(
+ [state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> t) mutable {
if (t.hasException()) {
auto tf2 = state.tryInvoke(std::move(t.exception()));
template <class T>
template <class F>
typename std::enable_if<
- detail::callableWith<F, exception_wrapper>::value &&
- !detail::Extract<F>::ReturnsFuture::value,
- Future<T>>::type
+ futures::detail::callableWith<F, exception_wrapper>::value &&
+ !futures::detail::Extract<F>::ReturnsFuture::value,
+ Future<T>>::type
Future<T>::onError(F&& func) {
static_assert(
- std::is_same<typename detail::Extract<F>::Return, Future<T>>::value,
+ std::is_same<typename futures::detail::Extract<F>::Return, Future<T>>::
+ value,
"Return type of onError callback must be T or Future<T>");
Promise<T> p;
auto f = p.getFuture();
setCallback_(
- [state = detail::makeCoreCallbackState(
+ [state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (t.hasException()) {
state.setTry(makeTryWith(
}
template <class T>
-Future<T>::Future(detail::EmptyConstruct) noexcept
- : core_(nullptr) {}
+Future<T>::Future(futures::detail::EmptyConstruct) noexcept : core_(nullptr) {}
// makeFuture
template <class T>
Future<T> makeFuture(Try<T>&& t) {
- return Future<T>(new detail::Core<T>(std::move(t)));
+ return Future<T>(new futures::detail::Core<T>(std::move(t)));
}
// via
// collectAll (variadic)
template <typename... Fs>
-typename detail::CollectAllVariadicContext<
- typename std::decay<Fs>::type::value_type...>::type
+typename futures::detail::CollectAllVariadicContext<
+ typename std::decay<Fs>::type::value_type...>::type
collectAll(Fs&&... fs) {
- auto ctx = std::make_shared<detail::CollectAllVariadicContext<
- typename std::decay<Fs>::type::value_type...>>();
- detail::collectVariadicHelper<detail::CollectAllVariadicContext>(
- ctx, std::forward<Fs>(fs)...);
+ auto ctx = std::make_shared<futures::detail::CollectAllVariadicContext<
+ typename std::decay<Fs>::type::value_type...>>();
+ futures::detail::collectVariadicHelper<
+ futures::detail::CollectAllVariadicContext>(ctx, std::forward<Fs>(fs)...);
return ctx->p.getFuture();
}
// collect (iterator)
+namespace futures {
namespace detail {
template <typename T>
std::atomic<bool> threw {false};
};
-}
+} // namespace detail
+} // namespace futures
template <class InputIterator>
-Future<typename detail::CollectContext<
- typename std::iterator_traits<InputIterator>::value_type::value_type>::Result>
+Future<typename futures::detail::CollectContext<typename std::iterator_traits<
+ InputIterator>::value_type::value_type>::Result>
collect(InputIterator first, InputIterator last) {
typedef
typename std::iterator_traits<InputIterator>::value_type::value_type T;
- auto ctx = std::make_shared<detail::CollectContext<T>>(
- std::distance(first, last));
+ auto ctx = std::make_shared<futures::detail::CollectContext<T>>(
+ std::distance(first, last));
mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
if (t.hasException()) {
if (!ctx->threw.exchange(true)) {
// collect (variadic)
template <typename... Fs>
-typename detail::CollectVariadicContext<
- typename std::decay<Fs>::type::value_type...>::type
+typename futures::detail::CollectVariadicContext<
+ typename std::decay<Fs>::type::value_type...>::type
collect(Fs&&... fs) {
- auto ctx = std::make_shared<detail::CollectVariadicContext<
- typename std::decay<Fs>::type::value_type...>>();
- detail::collectVariadicHelper<detail::CollectVariadicContext>(
- ctx, std::forward<Fs>(fs)...);
+ auto ctx = std::make_shared<futures::detail::CollectVariadicContext<
+ typename std::decay<Fs>::type::value_type...>>();
+ futures::detail::collectVariadicHelper<
+ futures::detail::CollectVariadicContext>(ctx, std::forward<Fs>(fs)...);
return ctx->p.getFuture();
}
}
typedef typename std::iterator_traits<It>::value_type::value_type ItT;
- typedef
- typename std::conditional<detail::callableWith<F, T&&, Try<ItT>&&>::value,
- Try<ItT>,
- ItT>::type Arg;
+ typedef typename std::conditional<
+ futures::detail::callableWith<F, T&&, Try<ItT>&&>::value,
+ Try<ItT>,
+ ItT>::type Arg;
typedef isTry<Arg> IsTry;
auto sfunc = std::make_shared<F>(std::move(func));
});
}
+namespace futures {
namespace detail {
template <class T>
assert(f.isReady());
}
-} // detail
+} // namespace detail
+} // namespace futures
template <class T>
Future<T>& Future<T>::wait() & {
- detail::waitImpl(*this);
+ futures::detail::waitImpl(*this);
return *this;
}
template <class T>
Future<T>&& Future<T>::wait() && {
- detail::waitImpl(*this);
+ futures::detail::waitImpl(*this);
return std::move(*this);
}
template <class T>
Future<T>& Future<T>::wait(Duration dur) & {
- detail::waitImpl(*this, dur);
+ futures::detail::waitImpl(*this, dur);
return *this;
}
template <class T>
Future<T>&& Future<T>::wait(Duration dur) && {
- detail::waitImpl(*this, dur);
+ futures::detail::waitImpl(*this, dur);
return std::move(*this);
}
template <class T>
Future<T>& Future<T>::waitVia(DrivableExecutor* e) & {
- detail::waitViaImpl(*this, e);
+ futures::detail::waitViaImpl(*this, e);
return *this;
}
template <class T>
Future<T>&& Future<T>::waitVia(DrivableExecutor* e) && {
- detail::waitViaImpl(*this, e);
+ futures::detail::waitViaImpl(*this, e);
return std::move(*this);
}
return std::move(waitVia(e).value());
}
+namespace futures {
namespace detail {
- template <class T>
- struct TryEquals {
- static bool equals(const Try<T>& t1, const Try<T>& t2) {
- return t1.value() == t2.value();
- }
- };
-}
+template <class T>
+struct TryEquals {
+ static bool equals(const Try<T>& t1, const Try<T>& t2) {
+ return t1.value() == t2.value();
+ }
+};
+} // namespace detail
+} // namespace futures
template <class T>
Future<bool> Future<T>::willEqual(Future<T>& f) {
return collectAll(*this, f).then([](const std::tuple<Try<T>, Try<T>>& t) {
if (std::get<0>(t).hasValue() && std::get<1>(t).hasValue()) {
- return detail::TryEquals<T>::equals(std::get<0>(t), std::get<1>(t));
+ return futures::detail::TryEquals<T>::equals(
+ std::get<0>(t), std::get<1>(t));
} else {
return false;
}
// replaced with F.
template <
typename F,
- typename FF = typename detail::FunctionReferenceToPointer<F>::type,
- typename R = detail::callableResult<T, FF>>
+ typename FF =
+ typename futures::detail::FunctionReferenceToPointer<F>::type,
+ typename R = futures::detail::callableResult<T, FF>>
typename R::Return then(F&& func) {
typedef typename R::Arg Arguments;
return thenImplementation<FF, R>(std::forward<FF>(func), Arguments());
/// });
template <class F>
typename std::enable_if<
- !detail::callableWith<F, exception_wrapper>::value &&
- !detail::Extract<F>::ReturnsFuture::value,
- Future<T>>::type
+ !futures::detail::callableWith<F, exception_wrapper>::value &&
+ !futures::detail::Extract<F>::ReturnsFuture::value,
+ Future<T>>::type
onError(F&& func);
/// Overload of onError where the error callback returns a Future<T>
template <class F>
typename std::enable_if<
- !detail::callableWith<F, exception_wrapper>::value &&
- detail::Extract<F>::ReturnsFuture::value,
- Future<T>>::type
+ !futures::detail::callableWith<F, exception_wrapper>::value &&
+ futures::detail::Extract<F>::ReturnsFuture::value,
+ Future<T>>::type
onError(F&& func);
/// Overload of onError that takes exception_wrapper and returns Future<T>
template <class F>
typename std::enable_if<
- detail::callableWith<F, exception_wrapper>::value &&
- detail::Extract<F>::ReturnsFuture::value,
- Future<T>>::type
+ futures::detail::callableWith<F, exception_wrapper>::value &&
+ futures::detail::Extract<F>::ReturnsFuture::value,
+ Future<T>>::type
onError(F&& func);
/// Overload of onError that takes exception_wrapper and returns T
template <class F>
typename std::enable_if<
- detail::callableWith<F, exception_wrapper>::value &&
- !detail::Extract<F>::ReturnsFuture::value,
- Future<T>>::type
+ futures::detail::callableWith<F, exception_wrapper>::value &&
+ !futures::detail::Extract<F>::ReturnsFuture::value,
+ Future<T>>::type
onError(F&& func);
/// func is like std::function<void()> and is executed unconditionally, and
}
protected:
- typedef detail::Core<T>* corePtr;
+ typedef futures::detail::Core<T>* corePtr;
// shared core state object
corePtr core_;
explicit
Future(corePtr obj) : core_(obj) {}
- explicit Future(detail::EmptyConstruct) noexcept;
+ explicit Future(futures::detail::EmptyConstruct) noexcept;
void detach();
// e.g. f.then([](Try<T> t){ return t.value(); });
template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<!R::ReturnsFuture::value, typename R::Return>::type
- thenImplementation(F&& func, detail::argResult<isTry, F, Args...>);
+ thenImplementation(F&& func, futures::detail::argResult<isTry, F, Args...>);
// Variant: returns a Future
// e.g. f.then([](Try<T> t){ return makeFuture<T>(t); });
template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<R::ReturnsFuture::value, typename R::Return>::type
- thenImplementation(F&& func, detail::argResult<isTry, F, Args...>);
+ thenImplementation(F&& func, futures::detail::argResult<isTry, F, Args...>);
Executor* getExecutor() { return core_->getExecutor(); }
void setExecutor(Executor* x, int8_t priority = Executor::MID_PRI) {
namespace folly {
+namespace futures {
namespace detail {
template <typename... Ts>
struct CollectAllVariadicContext {
std::atomic<bool> threw{false};
typedef Future<std::tuple<Ts...>> type;
};
-}
+} // namespace detail
+} // namespace futures
/// This namespace is for utility functions that would usually be static
/// members of Future, except they don't make sense there because they don't
/// is a Future<std::tuple<Try<T1>, Try<T2>, ...>>.
/// The Futures are moved in, so your copies are invalid.
template <typename... Fs>
-typename detail::CollectAllVariadicContext<
- typename std::decay<Fs>::type::value_type...>::type
+typename futures::detail::CollectAllVariadicContext<
+ typename std::decay<Fs>::type::value_type...>::type
collectAll(Fs&&... fs);
/// Like collectAll, but will short circuit on the first exception. Thus, the
/// type of the returned Future is std::vector<T> instead of
/// std::vector<Try<T>>
template <class InputIterator>
-Future<typename detail::CollectContext<
- typename std::iterator_traits<InputIterator>::value_type::value_type
->::result_type>
+Future<typename futures::detail::CollectContext<typename std::iterator_traits<
+ InputIterator>::value_type::value_type>::result_type>
collect(InputIterator first, InputIterator last);
/// Sugar for the most common case
/// type of the returned Future is std::tuple<T1, T2, ...> instead of
/// std::tuple<Try<T1>, Try<T2>, ...>
template <typename... Fs>
-typename detail::CollectVariadicContext<
- typename std::decay<Fs>::type::value_type...>::type
+typename futures::detail::CollectVariadicContext<
+ typename std::decay<Fs>::type::value_type...>::type
collect(Fs&&... fs);
/** The result is a pair of the index of the first Future to complete and
func must return a Future for each value in input
*/
-template <class Collection, class F,
- class ItT = typename std::iterator_traits<
- typename Collection::iterator>::value_type,
- class Result = typename detail::resultOf<F, ItT&&>::value_type>
-std::vector<Future<Result>>
-window(Collection input, F func, size_t n);
+template <
+ class Collection,
+ class F,
+ class ItT = typename std::iterator_traits<
+ typename Collection::iterator>::value_type,
+ class Result = typename futures::detail::resultOf<F, ItT&&>::value_type>
+std::vector<Future<Result>> window(Collection input, F func, size_t n);
template <typename F, typename T, typename ItT>
using MaybeTryArg = typename std::conditional<
- detail::callableWith<F, T&&, Try<ItT>&&>::value, Try<ItT>, ItT>::type;
+ futures::detail::callableWith<F, T&&, Try<ItT>&&>::value,
+ Try<ItT>,
+ ItT>::type;
template<typename F, typename T, typename Arg>
using isFutureResult = isFuture<typename std::result_of<F(T&&, Arg&&)>::type>;