Commit 5a81b5df authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Move futures helper types into folly::futures::detail

Summary:
[Folly] Move futures helper types into `folly::futures::detail`.

From `folly::detail`, where it would be easier to collide. Especially for names like `Core`.

Reviewed By: WillerZ

Differential Revision: D5460766

fbshipit-source-id: 3f7bff784bbb89c7c86d2f1824323d71321c7ad6
parent 05a686a7
...@@ -39,17 +39,22 @@ namespace folly { ...@@ -39,17 +39,22 @@ namespace folly {
class Timekeeper; class Timekeeper;
namespace futures {
namespace detail { namespace detail {
#if FOLLY_FUTURE_USING_FIBER #if FOLLY_FUTURE_USING_FIBER
typedef folly::fibers::Baton FutureBatonType; typedef folly::fibers::Baton FutureBatonType;
#else #else
typedef folly::Baton<> FutureBatonType; typedef folly::Baton<> FutureBatonType;
#endif #endif
} } // namespace detail
} // namespace futures
namespace detail { namespace detail {
std::shared_ptr<Timekeeper> getTimekeeperSingleton(); std::shared_ptr<Timekeeper> getTimekeeperSingleton();
} // namespace detail
namespace futures {
namespace detail {
// Guarantees that the stored functor is destructed before the stored promise // Guarantees that the stored functor is destructed before the stored promise
// may be fulfilled. Assumes the stored functor to be noexcept-destructible. // may be fulfilled. Assumes the stored functor to be noexcept-destructible.
template <typename T, typename F> template <typename T, typename F>
...@@ -123,11 +128,12 @@ inline auto makeCoreCallbackState(Promise<T>&& p, F&& f) noexcept( ...@@ -123,11 +128,12 @@ inline auto makeCoreCallbackState(Promise<T>&& p, F&& f) noexcept(
return CoreCallbackState<T, _t<std::decay<F>>>( return CoreCallbackState<T, _t<std::decay<F>>>(
std::move(p), std::forward<F>(f)); std::move(p), std::forward<F>(f));
} }
} } // namespace detail
} // namespace futures
template <class T> template <class T>
Future<T> Future<T>::makeEmpty() { Future<T> Future<T>::makeEmpty() {
return Future<T>(detail::EmptyConstruct{}); return Future<T>(futures::detail::EmptyConstruct{});
} }
template <class T> template <class T>
...@@ -178,12 +184,12 @@ Future<T>& Future<T>::operator=(Future<T2>&& other) { ...@@ -178,12 +184,12 @@ Future<T>& Future<T>::operator=(Future<T2>&& other) {
template <class T> template <class T>
template <class T2, typename> template <class T2, typename>
Future<T>::Future(T2&& val) 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 <class T>
template <typename T2> template <typename T2>
Future<T>::Future(typename std::enable_if<std::is_same<Unit, T2>::value>::type*) 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 <class T>
template < template <
...@@ -191,7 +197,9 @@ template < ...@@ -191,7 +197,9 @@ template <
typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>:: typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::
type> type>
Future<T>::Future(in_place_t, Args&&... args) 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> template <class T>
Future<T>::~Future() { Future<T>::~Future() {
...@@ -238,7 +246,9 @@ Future<T>::unwrap() { ...@@ -238,7 +246,9 @@ Future<T>::unwrap() {
template <class T> template <class T>
template <typename F, typename R, bool isTry, typename... Args> template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<!R::ReturnsFuture::value, typename R::Return>::type 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"); static_assert(sizeof...(Args) <= 1, "Then must take zero/one argument");
typedef typename R::ReturnsFuture::Inner B; typedef typename R::ReturnsFuture::Inner B;
...@@ -270,18 +280,18 @@ Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) { ...@@ -270,18 +280,18 @@ Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) {
persist beyond the callback, if it gets moved), and so it is an persist beyond the callback, if it gets moved), and so it is an
optimization to just make it shared from the get-go. optimization to just make it shared from the get-go.
Two subtle but important points about this design. detail::Core has no Two subtle but important points about this design. futures::detail::Core
back pointers to Future or Promise, so if Future or Promise get moved has no back pointers to Future or Promise, so if Future or Promise get
(and they will be moved in performant code) we don't have to do 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 anything fancy. And because we store the continuation in the
detail::Core, not in the Future, we can execute the continuation even futures::detail::Core, not in the Future, we can execute the continuation
after the Future has gone out of scope. This is an intentional design 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 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 some circumstances, but I think it should be explicit not implicit
in the destruction of the Future used to create it. in the destruction of the Future used to create it.
*/ */
setCallback_( setCallback_(
[state = detail::makeCoreCallbackState( [state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable { std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (!isTry && t.hasException()) { if (!isTry && t.hasException()) {
state.setException(std::move(t.exception())); state.setException(std::move(t.exception()));
...@@ -299,7 +309,9 @@ Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) { ...@@ -299,7 +309,9 @@ Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) {
template <class T> template <class T>
template <typename F, typename R, bool isTry, typename... Args> template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<R::ReturnsFuture::value, typename R::Return>::type 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"); static_assert(sizeof...(Args) <= 1, "Then must take zero/one argument");
typedef typename R::ReturnsFuture::Inner B; typedef typename R::ReturnsFuture::Inner B;
...@@ -313,7 +325,7 @@ Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) { ...@@ -313,7 +325,7 @@ Future<T>::thenImplementation(F&& func, detail::argResult<isTry, F, Args...>) {
f.core_->setExecutorNoLock(getExecutor()); f.core_->setExecutorNoLock(getExecutor());
setCallback_( setCallback_(
[state = detail::makeCoreCallbackState( [state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable { std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (!isTry && t.hasException()) { if (!isTry && t.hasException()) {
state.setException(std::move(t.exception())); state.setException(std::move(t.exception()));
...@@ -336,9 +348,9 @@ template <typename T> ...@@ -336,9 +348,9 @@ template <typename T>
template <typename R, typename Caller, typename... Args> template <typename R, typename Caller, typename... Args>
Future<typename isFuture<R>::Inner> Future<typename isFuture<R>::Inner>
Future<T>::then(R(Caller::*func)(Args...), Caller *instance) { Future<T>::then(R(Caller::*func)(Args...), Caller *instance) {
typedef typename std::remove_cv< typedef typename std::remove_cv<typename std::remove_reference<
typename std::remove_reference< typename futures::detail::ArgType<Args...>::FirstArg>::type>::type
typename detail::ArgType<Args...>::FirstArg>::type>::type FirstArg; FirstArg;
return then([instance, func](Try<T>&& t){ return then([instance, func](Try<T>&& t){
return (instance->*func)(t.template get<isTry<FirstArg>::value, Args>()...); return (instance->*func)(t.template get<isTry<FirstArg>::value, Args>()...);
}); });
...@@ -353,13 +365,15 @@ Future<Unit> Future<T>::then() { ...@@ -353,13 +365,15 @@ Future<Unit> Future<T>::then() {
template <class T> template <class T>
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
!detail::callableWith<F, exception_wrapper>::value && !futures::detail::callableWith<F, exception_wrapper>::value &&
!detail::Extract<F>::ReturnsFuture::value, !futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type Future<T>>::type
Future<T>::onError(F&& func) { 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( 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>"); "Return type of onError callback must be T or Future<T>");
Promise<T> p; Promise<T> p;
...@@ -367,7 +381,7 @@ Future<T>::onError(F&& func) { ...@@ -367,7 +381,7 @@ Future<T>::onError(F&& func) {
auto f = p.getFuture(); auto f = p.getFuture();
setCallback_( setCallback_(
[state = detail::makeCoreCallbackState( [state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable { std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (auto e = t.template tryGetExceptionObject<Exn>()) { if (auto e = t.template tryGetExceptionObject<Exn>()) {
state.setTry(makeTryWith([&] { return state.invoke(*e); })); state.setTry(makeTryWith([&] { return state.invoke(*e); }));
...@@ -383,20 +397,23 @@ Future<T>::onError(F&& func) { ...@@ -383,20 +397,23 @@ Future<T>::onError(F&& func) {
template <class T> template <class T>
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
!detail::callableWith<F, exception_wrapper>::value && !futures::detail::callableWith<F, exception_wrapper>::value &&
detail::Extract<F>::ReturnsFuture::value, futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type Future<T>>::type
Future<T>::onError(F&& func) { Future<T>::onError(F&& func) {
static_assert( 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>"); "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; Promise<T> p;
auto f = p.getFuture(); auto f = p.getFuture();
setCallback_( setCallback_(
[state = detail::makeCoreCallbackState( [state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable { std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (auto e = t.template tryGetExceptionObject<Exn>()) { if (auto e = t.template tryGetExceptionObject<Exn>()) {
auto tf2 = state.tryInvoke(*e); auto tf2 = state.tryInvoke(*e);
...@@ -433,18 +450,20 @@ Future<T> Future<T>::onTimeout(Duration dur, F&& func, Timekeeper* tk) { ...@@ -433,18 +450,20 @@ Future<T> Future<T>::onTimeout(Duration dur, F&& func, Timekeeper* tk) {
template <class T> template <class T>
template <class F> template <class F>
typename std::enable_if<detail::callableWith<F, exception_wrapper>::value && typename std::enable_if<
detail::Extract<F>::ReturnsFuture::value, futures::detail::callableWith<F, exception_wrapper>::value &&
futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type Future<T>>::type
Future<T>::onError(F&& func) { Future<T>::onError(F&& func) {
static_assert( 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>"); "Return type of onError callback must be T or Future<T>");
Promise<T> p; Promise<T> p;
auto f = p.getFuture(); auto f = p.getFuture();
setCallback_( setCallback_(
[state = detail::makeCoreCallbackState( [state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> t) mutable { std::move(p), std::forward<F>(func))](Try<T> t) mutable {
if (t.hasException()) { if (t.hasException()) {
auto tf2 = state.tryInvoke(std::move(t.exception())); auto tf2 = state.tryInvoke(std::move(t.exception()));
...@@ -467,18 +486,19 @@ Future<T>::onError(F&& func) { ...@@ -467,18 +486,19 @@ Future<T>::onError(F&& func) {
template <class T> template <class T>
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
detail::callableWith<F, exception_wrapper>::value && futures::detail::callableWith<F, exception_wrapper>::value &&
!detail::Extract<F>::ReturnsFuture::value, !futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type Future<T>>::type
Future<T>::onError(F&& func) { Future<T>::onError(F&& func) {
static_assert( 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>"); "Return type of onError callback must be T or Future<T>");
Promise<T> p; Promise<T> p;
auto f = p.getFuture(); auto f = p.getFuture();
setCallback_( setCallback_(
[state = detail::makeCoreCallbackState( [state = futures::detail::makeCoreCallbackState(
std::move(p), std::forward<F>(func))](Try<T> && t) mutable { std::move(p), std::forward<F>(func))](Try<T> && t) mutable {
if (t.hasException()) { if (t.hasException()) {
state.setTry(makeTryWith( state.setTry(makeTryWith(
...@@ -574,8 +594,7 @@ void Future<T>::raise(exception_wrapper exception) { ...@@ -574,8 +594,7 @@ void Future<T>::raise(exception_wrapper exception) {
} }
template <class T> template <class T>
Future<T>::Future(detail::EmptyConstruct) noexcept Future<T>::Future(futures::detail::EmptyConstruct) noexcept : core_(nullptr) {}
: core_(nullptr) {}
// makeFuture // makeFuture
...@@ -638,7 +657,7 @@ makeFuture(E const& e) { ...@@ -638,7 +657,7 @@ makeFuture(E const& e) {
template <class T> template <class T>
Future<T> makeFuture(Try<T>&& 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 // via
...@@ -660,13 +679,13 @@ void mapSetCallback(InputIterator first, InputIterator last, F func) { ...@@ -660,13 +679,13 @@ void mapSetCallback(InputIterator first, InputIterator last, F func) {
// collectAll (variadic) // collectAll (variadic)
template <typename... Fs> template <typename... Fs>
typename detail::CollectAllVariadicContext< typename futures::detail::CollectAllVariadicContext<
typename std::decay<Fs>::type::value_type...>::type typename std::decay<Fs>::type::value_type...>::type
collectAll(Fs&&... fs) { collectAll(Fs&&... fs) {
auto ctx = std::make_shared<detail::CollectAllVariadicContext< auto ctx = std::make_shared<futures::detail::CollectAllVariadicContext<
typename std::decay<Fs>::type::value_type...>>(); typename std::decay<Fs>::type::value_type...>>();
detail::collectVariadicHelper<detail::CollectAllVariadicContext>( futures::detail::collectVariadicHelper<
ctx, std::forward<Fs>(fs)...); futures::detail::CollectAllVariadicContext>(ctx, std::forward<Fs>(fs)...);
return ctx->p.getFuture(); return ctx->p.getFuture();
} }
...@@ -699,6 +718,7 @@ collectAll(InputIterator first, InputIterator last) { ...@@ -699,6 +718,7 @@ collectAll(InputIterator first, InputIterator last) {
// collect (iterator) // collect (iterator)
namespace futures {
namespace detail { namespace detail {
template <typename T> template <typename T>
...@@ -737,16 +757,17 @@ struct CollectContext { ...@@ -737,16 +757,17 @@ struct CollectContext {
std::atomic<bool> threw {false}; std::atomic<bool> threw {false};
}; };
} } // namespace detail
} // namespace futures
template <class InputIterator> template <class InputIterator>
Future<typename detail::CollectContext< Future<typename futures::detail::CollectContext<typename std::iterator_traits<
typename std::iterator_traits<InputIterator>::value_type::value_type>::Result> InputIterator>::value_type::value_type>::Result>
collect(InputIterator first, InputIterator last) { collect(InputIterator first, InputIterator last) {
typedef typedef
typename std::iterator_traits<InputIterator>::value_type::value_type T; typename std::iterator_traits<InputIterator>::value_type::value_type T;
auto ctx = std::make_shared<detail::CollectContext<T>>( auto ctx = std::make_shared<futures::detail::CollectContext<T>>(
std::distance(first, last)); std::distance(first, last));
mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) { mapSetCallback<T>(first, last, [ctx](size_t i, Try<T>&& t) {
if (t.hasException()) { if (t.hasException()) {
...@@ -763,13 +784,13 @@ collect(InputIterator first, InputIterator last) { ...@@ -763,13 +784,13 @@ collect(InputIterator first, InputIterator last) {
// collect (variadic) // collect (variadic)
template <typename... Fs> template <typename... Fs>
typename detail::CollectVariadicContext< typename futures::detail::CollectVariadicContext<
typename std::decay<Fs>::type::value_type...>::type typename std::decay<Fs>::type::value_type...>::type
collect(Fs&&... fs) { collect(Fs&&... fs) {
auto ctx = std::make_shared<detail::CollectVariadicContext< auto ctx = std::make_shared<futures::detail::CollectVariadicContext<
typename std::decay<Fs>::type::value_type...>>(); typename std::decay<Fs>::type::value_type...>>();
detail::collectVariadicHelper<detail::CollectVariadicContext>( futures::detail::collectVariadicHelper<
ctx, std::forward<Fs>(fs)...); futures::detail::CollectVariadicContext>(ctx, std::forward<Fs>(fs)...);
return ctx->p.getFuture(); return ctx->p.getFuture();
} }
...@@ -878,8 +899,8 @@ Future<T> reduce(It first, It last, T&& initial, F&& func) { ...@@ -878,8 +899,8 @@ Future<T> reduce(It first, It last, T&& initial, F&& func) {
} }
typedef typename std::iterator_traits<It>::value_type::value_type ItT; typedef typename std::iterator_traits<It>::value_type::value_type ItT;
typedef typedef typename std::conditional<
typename std::conditional<detail::callableWith<F, T&&, Try<ItT>&&>::value, futures::detail::callableWith<F, T&&, Try<ItT>&&>::value,
Try<ItT>, Try<ItT>,
ItT>::type Arg; ItT>::type Arg;
typedef isTry<Arg> IsTry; typedef isTry<Arg> IsTry;
...@@ -1083,6 +1104,7 @@ Future<T> Future<T>::delayed(Duration dur, Timekeeper* tk) { ...@@ -1083,6 +1104,7 @@ Future<T> Future<T>::delayed(Duration dur, Timekeeper* tk) {
}); });
} }
namespace futures {
namespace detail { namespace detail {
template <class T> template <class T>
...@@ -1130,41 +1152,42 @@ void waitViaImpl(Future<T>& f, DrivableExecutor* e) { ...@@ -1130,41 +1152,42 @@ void waitViaImpl(Future<T>& f, DrivableExecutor* e) {
assert(f.isReady()); assert(f.isReady());
} }
} // detail } // namespace detail
} // namespace futures
template <class T> template <class T>
Future<T>& Future<T>::wait() & { Future<T>& Future<T>::wait() & {
detail::waitImpl(*this); futures::detail::waitImpl(*this);
return *this; return *this;
} }
template <class T> template <class T>
Future<T>&& Future<T>::wait() && { Future<T>&& Future<T>::wait() && {
detail::waitImpl(*this); futures::detail::waitImpl(*this);
return std::move(*this); return std::move(*this);
} }
template <class T> template <class T>
Future<T>& Future<T>::wait(Duration dur) & { Future<T>& Future<T>::wait(Duration dur) & {
detail::waitImpl(*this, dur); futures::detail::waitImpl(*this, dur);
return *this; return *this;
} }
template <class T> template <class T>
Future<T>&& Future<T>::wait(Duration dur) && { Future<T>&& Future<T>::wait(Duration dur) && {
detail::waitImpl(*this, dur); futures::detail::waitImpl(*this, dur);
return std::move(*this); return std::move(*this);
} }
template <class T> template <class T>
Future<T>& Future<T>::waitVia(DrivableExecutor* e) & { Future<T>& Future<T>::waitVia(DrivableExecutor* e) & {
detail::waitViaImpl(*this, e); futures::detail::waitViaImpl(*this, e);
return *this; return *this;
} }
template <class T> template <class T>
Future<T>&& Future<T>::waitVia(DrivableExecutor* e) && { Future<T>&& Future<T>::waitVia(DrivableExecutor* e) && {
detail::waitViaImpl(*this, e); futures::detail::waitViaImpl(*this, e);
return std::move(*this); return std::move(*this);
} }
...@@ -1188,20 +1211,23 @@ T Future<T>::getVia(DrivableExecutor* e) { ...@@ -1188,20 +1211,23 @@ T Future<T>::getVia(DrivableExecutor* e) {
return std::move(waitVia(e).value()); return std::move(waitVia(e).value());
} }
namespace futures {
namespace detail { namespace detail {
template <class T> template <class T>
struct TryEquals { struct TryEquals {
static bool equals(const Try<T>& t1, const Try<T>& t2) { static bool equals(const Try<T>& t1, const Try<T>& t2) {
return t1.value() == t2.value(); return t1.value() == t2.value();
} }
}; };
} } // namespace detail
} // namespace futures
template <class T> template <class T>
Future<bool> Future<T>::willEqual(Future<T>& f) { Future<bool> Future<T>::willEqual(Future<T>& f) {
return collectAll(*this, f).then([](const std::tuple<Try<T>, Try<T>>& t) { return collectAll(*this, f).then([](const std::tuple<Try<T>, Try<T>>& t) {
if (std::get<0>(t).hasValue() && std::get<1>(t).hasValue()) { 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 { } else {
return false; return false;
} }
......
...@@ -38,6 +38,7 @@ struct isTry : std::false_type {}; ...@@ -38,6 +38,7 @@ struct isTry : std::false_type {};
template <typename T> template <typename T>
struct isTry<Try<T>> : std::true_type {}; struct isTry<Try<T>> : std::true_type {};
namespace futures {
namespace detail { namespace detail {
template <class> class Core; template <class> class Core;
...@@ -154,7 +155,8 @@ struct FunctionReferenceToPointer<R (&)(Args...)> { ...@@ -154,7 +155,8 @@ struct FunctionReferenceToPointer<R (&)(Args...)> {
using type = R (*)(Args...); using type = R (*)(Args...);
}; };
} // detail } // namespace detail
} // namespace futures
class Timekeeper; class Timekeeper;
......
...@@ -210,8 +210,9 @@ class Future { ...@@ -210,8 +210,9 @@ class Future {
// replaced with F. // replaced with F.
template < template <
typename F, typename F,
typename FF = typename detail::FunctionReferenceToPointer<F>::type, typename FF =
typename R = detail::callableResult<T, FF>> typename futures::detail::FunctionReferenceToPointer<F>::type,
typename R = futures::detail::callableResult<T, FF>>
typename R::Return then(F&& func) { typename R::Return then(F&& func) {
typedef typename R::Arg Arguments; typedef typename R::Arg Arguments;
return thenImplementation<FF, R>(std::forward<FF>(func), Arguments()); return thenImplementation<FF, R>(std::forward<FF>(func), Arguments());
...@@ -271,32 +272,32 @@ class Future { ...@@ -271,32 +272,32 @@ class Future {
/// }); /// });
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
!detail::callableWith<F, exception_wrapper>::value && !futures::detail::callableWith<F, exception_wrapper>::value &&
!detail::Extract<F>::ReturnsFuture::value, !futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type Future<T>>::type
onError(F&& func); onError(F&& func);
/// Overload of onError where the error callback returns a Future<T> /// Overload of onError where the error callback returns a Future<T>
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
!detail::callableWith<F, exception_wrapper>::value && !futures::detail::callableWith<F, exception_wrapper>::value &&
detail::Extract<F>::ReturnsFuture::value, futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type Future<T>>::type
onError(F&& func); onError(F&& func);
/// Overload of onError that takes exception_wrapper and returns Future<T> /// Overload of onError that takes exception_wrapper and returns Future<T>
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
detail::callableWith<F, exception_wrapper>::value && futures::detail::callableWith<F, exception_wrapper>::value &&
detail::Extract<F>::ReturnsFuture::value, futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type Future<T>>::type
onError(F&& func); onError(F&& func);
/// Overload of onError that takes exception_wrapper and returns T /// Overload of onError that takes exception_wrapper and returns T
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
detail::callableWith<F, exception_wrapper>::value && futures::detail::callableWith<F, exception_wrapper>::value &&
!detail::Extract<F>::ReturnsFuture::value, !futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type Future<T>>::type
onError(F&& func); onError(F&& func);
...@@ -482,7 +483,7 @@ class Future { ...@@ -482,7 +483,7 @@ class Future {
} }
protected: protected:
typedef detail::Core<T>* corePtr; typedef futures::detail::Core<T>* corePtr;
// shared core state object // shared core state object
corePtr core_; corePtr core_;
...@@ -490,7 +491,7 @@ class Future { ...@@ -490,7 +491,7 @@ class Future {
explicit explicit
Future(corePtr obj) : core_(obj) {} Future(corePtr obj) : core_(obj) {}
explicit Future(detail::EmptyConstruct) noexcept; explicit Future(futures::detail::EmptyConstruct) noexcept;
void detach(); void detach();
...@@ -529,13 +530,13 @@ class Future { ...@@ -529,13 +530,13 @@ class Future {
// e.g. f.then([](Try<T> t){ return t.value(); }); // e.g. f.then([](Try<T> t){ return t.value(); });
template <typename F, typename R, bool isTry, typename... Args> template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<!R::ReturnsFuture::value, typename R::Return>::type 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 // Variant: returns a Future
// e.g. f.then([](Try<T> t){ return makeFuture<T>(t); }); // e.g. f.then([](Try<T> t){ return makeFuture<T>(t); });
template <typename F, typename R, bool isTry, typename... Args> template <typename F, typename R, bool isTry, typename... Args>
typename std::enable_if<R::ReturnsFuture::value, typename R::Return>::type 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(); } Executor* getExecutor() { return core_->getExecutor(); }
void setExecutor(Executor* x, int8_t priority = Executor::MID_PRI) { void setExecutor(Executor* x, int8_t priority = Executor::MID_PRI) {
......
...@@ -26,12 +26,12 @@ namespace folly { ...@@ -26,12 +26,12 @@ namespace folly {
template <class T> template <class T>
Promise<T> Promise<T>::makeEmpty() noexcept { Promise<T> Promise<T>::makeEmpty() noexcept {
return Promise<T>(detail::EmptyConstruct{}); return Promise<T>(futures::detail::EmptyConstruct{});
} }
template <class T> template <class T>
Promise<T>::Promise() : retrieved_(false), core_(new detail::Core<T>()) Promise<T>::Promise()
{} : retrieved_(false), core_(new futures::detail::Core<T>()) {}
template <class T> template <class T>
Promise<T>::Promise(Promise<T>&& other) noexcept Promise<T>::Promise(Promise<T>&& other) noexcept
...@@ -65,7 +65,7 @@ void Promise<T>::throwIfRetrieved() { ...@@ -65,7 +65,7 @@ void Promise<T>::throwIfRetrieved() {
} }
template <class T> template <class T>
Promise<T>::Promise(detail::EmptyConstruct) noexcept Promise<T>::Promise(futures::detail::EmptyConstruct) noexcept
: retrieved_(false), core_(nullptr) {} : retrieved_(false), core_(nullptr) {}
template <class T> template <class T>
......
...@@ -25,11 +25,13 @@ namespace folly { ...@@ -25,11 +25,13 @@ namespace folly {
// forward declaration // forward declaration
template <class T> class Future; template <class T> class Future;
namespace futures {
namespace detail { namespace detail {
struct EmptyConstruct {}; struct EmptyConstruct {};
template <typename T, typename F> template <typename T, typename F>
class CoreCallbackState; class CoreCallbackState;
} } // namespace detail
} // namespace futures
template <class T> template <class T>
class Promise { class Promise {
...@@ -107,7 +109,7 @@ class Promise { ...@@ -107,7 +109,7 @@ class Promise {
typedef typename Future<T>::corePtr corePtr; typedef typename Future<T>::corePtr corePtr;
template <class> friend class Future; template <class> friend class Future;
template <class, class> template <class, class>
friend class detail::CoreCallbackState; friend class futures::detail::CoreCallbackState;
// Whether the Future has been retrieved (a one-time operation). // Whether the Future has been retrieved (a one-time operation).
bool retrieved_; bool retrieved_;
...@@ -115,7 +117,7 @@ class Promise { ...@@ -115,7 +117,7 @@ class Promise {
// shared core state object // shared core state object
corePtr core_; corePtr core_;
explicit Promise(detail::EmptyConstruct) noexcept; explicit Promise(futures::detail::EmptyConstruct) noexcept;
void throwIfFulfilled(); void throwIfFulfilled();
void throwIfRetrieved(); void throwIfRetrieved();
......
...@@ -34,7 +34,9 @@ ...@@ -34,7 +34,9 @@
#include <folly/io/async/Request.h> #include <folly/io/async/Request.h>
namespace folly { namespace detail { namespace folly {
namespace futures {
namespace detail {
/* /*
OnlyCallback OnlyCallback
...@@ -450,4 +452,6 @@ void collectVariadicHelper(const std::shared_ptr<T<Ts...>>& ctx, ...@@ -450,4 +452,6 @@ void collectVariadicHelper(const std::shared_ptr<T<Ts...>>& ctx,
collectVariadicHelper(ctx, std::forward<TTail>(tail)...); collectVariadicHelper(ctx, std::forward<TTail>(tail)...);
} }
}} // folly::detail } // namespace detail
} // namespace futures
} // namespace folly
...@@ -21,7 +21,9 @@ ...@@ -21,7 +21,9 @@
#include <folly/MicroSpinLock.h> #include <folly/MicroSpinLock.h>
namespace folly { namespace detail { namespace folly {
namespace futures {
namespace detail {
/// Finite State Machine helper base class. /// Finite State Machine helper base class.
/// Inherit from this. /// Inherit from this.
...@@ -126,5 +128,6 @@ public: ...@@ -126,5 +128,6 @@ public:
#define FSM_BREAK done = true; break; #define FSM_BREAK done = true; break;
#define FSM_END }}} #define FSM_END }}}
} // namespace detail
}} // folly::detail } // namespace futures
} // namespace folly
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
namespace folly { namespace folly {
namespace futures {
namespace detail { namespace detail {
template <typename... Ts> template <typename... Ts>
struct CollectAllVariadicContext { struct CollectAllVariadicContext {
...@@ -65,7 +66,8 @@ struct CollectVariadicContext { ...@@ -65,7 +66,8 @@ struct CollectVariadicContext {
std::atomic<bool> threw{false}; std::atomic<bool> threw{false};
typedef Future<std::tuple<Ts...>> type; typedef Future<std::tuple<Ts...>> type;
}; };
} } // namespace detail
} // namespace futures
/// This namespace is for utility functions that would usually be static /// 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 /// members of Future, except they don't make sense there because they don't
...@@ -228,7 +230,7 @@ auto collectAll(Collection&& c) -> decltype(collectAll(c.begin(), c.end())) { ...@@ -228,7 +230,7 @@ auto collectAll(Collection&& c) -> decltype(collectAll(c.begin(), c.end())) {
/// is a Future<std::tuple<Try<T1>, Try<T2>, ...>>. /// is a Future<std::tuple<Try<T1>, Try<T2>, ...>>.
/// The Futures are moved in, so your copies are invalid. /// The Futures are moved in, so your copies are invalid.
template <typename... Fs> template <typename... Fs>
typename detail::CollectAllVariadicContext< typename futures::detail::CollectAllVariadicContext<
typename std::decay<Fs>::type::value_type...>::type typename std::decay<Fs>::type::value_type...>::type
collectAll(Fs&&... fs); collectAll(Fs&&... fs);
...@@ -236,9 +238,8 @@ collectAll(Fs&&... fs); ...@@ -236,9 +238,8 @@ collectAll(Fs&&... fs);
/// type of the returned Future is std::vector<T> instead of /// type of the returned Future is std::vector<T> instead of
/// std::vector<Try<T>> /// std::vector<Try<T>>
template <class InputIterator> template <class InputIterator>
Future<typename detail::CollectContext< Future<typename futures::detail::CollectContext<typename std::iterator_traits<
typename std::iterator_traits<InputIterator>::value_type::value_type InputIterator>::value_type::value_type>::result_type>
>::result_type>
collect(InputIterator first, InputIterator last); collect(InputIterator first, InputIterator last);
/// Sugar for the most common case /// Sugar for the most common case
...@@ -251,7 +252,7 @@ auto collect(Collection&& c) -> decltype(collect(c.begin(), c.end())) { ...@@ -251,7 +252,7 @@ auto collect(Collection&& c) -> decltype(collect(c.begin(), c.end())) {
/// type of the returned Future is std::tuple<T1, T2, ...> instead of /// type of the returned Future is std::tuple<T1, T2, ...> instead of
/// std::tuple<Try<T1>, Try<T2>, ...> /// std::tuple<Try<T1>, Try<T2>, ...>
template <typename... Fs> template <typename... Fs>
typename detail::CollectVariadicContext< typename futures::detail::CollectVariadicContext<
typename std::decay<Fs>::type::value_type...>::type typename std::decay<Fs>::type::value_type...>::type
collect(Fs&&... fs); collect(Fs&&... fs);
...@@ -317,16 +318,19 @@ auto collectN(Collection&& c, size_t n) ...@@ -317,16 +318,19 @@ auto collectN(Collection&& c, size_t n)
func must return a Future for each value in input func must return a Future for each value in input
*/ */
template <class Collection, class F, template <
class Collection,
class F,
class ItT = typename std::iterator_traits< class ItT = typename std::iterator_traits<
typename Collection::iterator>::value_type, typename Collection::iterator>::value_type,
class Result = typename detail::resultOf<F, ItT&&>::value_type> class Result = typename futures::detail::resultOf<F, ItT&&>::value_type>
std::vector<Future<Result>> std::vector<Future<Result>> window(Collection input, F func, size_t n);
window(Collection input, F func, size_t n);
template <typename F, typename T, typename ItT> template <typename F, typename T, typename ItT>
using MaybeTryArg = typename std::conditional< 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> template<typename F, typename T, typename Arg>
using isFutureResult = isFuture<typename std::result_of<F(T&&, Arg&&)>::type>; using isFutureResult = isFuture<typename std::result_of<F(T&&, Arg&&)>::type>;
......
...@@ -26,7 +26,7 @@ TEST(Core, size) { ...@@ -26,7 +26,7 @@ TEST(Core, size) {
typename std::aligned_storage<lambdaBufSize>::type lambdaBuf_; typename std::aligned_storage<lambdaBufSize>::type lambdaBuf_;
folly::Optional<Try<Unit>> result_; folly::Optional<Try<Unit>> result_;
std::function<void(Try<Unit>&&)> callback_; std::function<void(Try<Unit>&&)> callback_;
detail::FSM<detail::State> fsm_; futures::detail::FSM<futures::detail::State> fsm_;
std::atomic<unsigned char> attached_; std::atomic<unsigned char> attached_;
std::atomic<bool> active_; std::atomic<bool> active_;
std::atomic<bool> interruptHandlerSet_; std::atomic<bool> interruptHandlerSet_;
...@@ -40,5 +40,5 @@ TEST(Core, size) { ...@@ -40,5 +40,5 @@ TEST(Core, size) {
}; };
// If this number goes down, it's fine! // If this number goes down, it's fine!
// If it goes up, please seek professional advice ;-) // If it goes up, please seek professional advice ;-)
EXPECT_GE(sizeof(Gold), sizeof(detail::Core<Unit>)); EXPECT_GE(sizeof(Gold), sizeof(futures::detail::Core<Unit>));
} }
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <folly/futures/detail/FSM.h> #include <folly/futures/detail/FSM.h>
#include <folly/portability/GTest.h> #include <folly/portability/GTest.h>
using namespace folly::detail; using namespace folly::futures::detail;
enum class State { A, B }; enum class State { A, B };
......
...@@ -648,7 +648,7 @@ TEST(Future, finishBigLambda) { ...@@ -648,7 +648,7 @@ TEST(Future, finishBigLambda) {
// bulk_data, to be captured in the lambda passed to Future::then. // bulk_data, to be captured in the lambda passed to Future::then.
// This is meant to force that the lambda can't be stored inside // This is meant to force that the lambda can't be stored inside
// the Future object. // the Future object.
std::array<char, sizeof(detail::Core<int>)> bulk_data = {{0}}; std::array<char, sizeof(futures::detail::Core<int>)> bulk_data = {{0}};
// suppress gcc warning about bulk_data not being used // suppress gcc warning about bulk_data not being used
EXPECT_EQ(bulk_data[0], 0); EXPECT_EQ(bulk_data[0], 0);
......
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