Commit 8401bbaf authored by Sven Over's avatar Sven Over Committed by Facebook Github Bot

Future: some fixes re: handling of universal references

Summary:
Callables that are passed as rvalues to makeFutureWith should be
executed as rvalues.
Generally callables that get captured by value should be executed
as rvalues, to allow passing e.g. folly::Partial objects that contain
move-only objects like unique_ptr or folly::Promise.
`collect` would move out of parameters passed as lvalues.

Reviewed By: fugalh

Differential Revision: D5120420

fbshipit-source-id: 1633c6b7e3fbb562f4d31e21d28c98b053de9912
parent ba9034b9
...@@ -324,7 +324,7 @@ template <class T> ...@@ -324,7 +324,7 @@ template <class T>
template <class F> template <class F>
Future<T> Future<T>::ensure(F&& func) { Future<T> Future<T>::ensure(F&& func) {
return this->then([funcw = std::forward<F>(func)](Try<T> && t) mutable { return this->then([funcw = std::forward<F>(func)](Try<T> && t) mutable {
funcw(); std::move(funcw)();
return makeFuture(std::move(t)); return makeFuture(std::move(t));
}); });
} }
...@@ -333,7 +333,7 @@ template <class T> ...@@ -333,7 +333,7 @@ template <class T>
template <class F> template <class F>
Future<T> Future<T>::onTimeout(Duration dur, F&& func, Timekeeper* tk) { Future<T> Future<T>::onTimeout(Duration dur, F&& func, Timekeeper* tk) {
return within(dur, tk).onError([funcw = std::forward<F>(func)]( return within(dur, tk).onError([funcw = std::forward<F>(func)](
TimedOut const&) { return funcw(); }); TimedOut const&) { return std::move(funcw)(); });
} }
template <class T> template <class T>
...@@ -457,8 +457,7 @@ inline Future<T> Future<T>::via(Executor* executor, int8_t priority) & { ...@@ -457,8 +457,7 @@ inline Future<T> Future<T>::via(Executor* executor, int8_t priority) & {
template <class Func> template <class Func>
auto via(Executor* x, Func&& func) auto via(Executor* x, Func&& func)
-> Future<typename isFuture<decltype(func())>::Inner> -> Future<typename isFuture<decltype(std::declval<Func>()())>::Inner> {
{
// TODO make this actually more performant. :-P #7260175 // TODO make this actually more performant. :-P #7260175
return via(x).then(std::forward<Func>(func)); return via(x).then(std::forward<Func>(func));
} }
...@@ -504,7 +503,7 @@ makeFutureWith(F&& func) { ...@@ -504,7 +503,7 @@ makeFutureWith(F&& func) {
using InnerType = using InnerType =
typename isFuture<typename std::result_of<F()>::type>::Inner; typename isFuture<typename std::result_of<F()>::type>::Inner;
try { try {
return func(); return std::forward<F>(func)();
} catch (std::exception& e) { } catch (std::exception& e) {
return makeFuture<InnerType>( return makeFuture<InnerType>(
exception_wrapper(std::current_exception(), e)); exception_wrapper(std::current_exception(), e));
...@@ -522,9 +521,8 @@ typename std::enable_if< ...@@ -522,9 +521,8 @@ typename std::enable_if<
makeFutureWith(F&& func) { makeFutureWith(F&& func) {
using LiftedResult = using LiftedResult =
typename Unit::Lift<typename std::result_of<F()>::type>::type; typename Unit::Lift<typename std::result_of<F()>::type>::type;
return makeFuture<LiftedResult>(makeTryWith([&func]() mutable { return makeFuture<LiftedResult>(
return func(); makeTryWith([&func]() mutable { return std::forward<F>(func)(); }));
}));
} }
template <class T> template <class T>
...@@ -574,7 +572,7 @@ collectAll(Fs&&... fs) { ...@@ -574,7 +572,7 @@ collectAll(Fs&&... fs) {
auto ctx = std::make_shared<detail::CollectAllVariadicContext< auto ctx = std::make_shared<detail::CollectAllVariadicContext<
typename std::decay<Fs>::type::value_type...>>(); typename std::decay<Fs>::type::value_type...>>();
detail::collectVariadicHelper<detail::CollectAllVariadicContext>( detail::collectVariadicHelper<detail::CollectAllVariadicContext>(
ctx, std::forward<typename std::decay<Fs>::type>(fs)...); ctx, std::forward<Fs>(fs)...);
return ctx->p.getFuture(); return ctx->p.getFuture();
} }
...@@ -677,7 +675,7 @@ collect(Fs&&... fs) { ...@@ -677,7 +675,7 @@ collect(Fs&&... fs) {
auto ctx = std::make_shared<detail::CollectVariadicContext< auto ctx = std::make_shared<detail::CollectVariadicContext<
typename std::decay<Fs>::type::value_type...>>(); typename std::decay<Fs>::type::value_type...>>();
detail::collectVariadicHelper<detail::CollectVariadicContext>( detail::collectVariadicHelper<detail::CollectVariadicContext>(
ctx, std::forward<typename std::decay<Fs>::type>(fs)...); ctx, std::forward<Fs>(fs)...);
return ctx->p.getFuture(); return ctx->p.getFuture();
} }
......
...@@ -470,9 +470,11 @@ template <template <typename ...> class T, typename... Ts, ...@@ -470,9 +470,11 @@ template <template <typename ...> class T, typename... Ts,
typename THead, typename... TTail> typename THead, typename... TTail>
void collectVariadicHelper(const std::shared_ptr<T<Ts...>>& ctx, void collectVariadicHelper(const std::shared_ptr<T<Ts...>>& ctx,
THead&& head, TTail&&... tail) { THead&& head, TTail&&... tail) {
head.setCallback_([ctx](Try<typename THead::value_type>&& t) { using ValueType = typename std::decay<THead>::type::value_type;
ctx->template setPartialResult<typename THead::value_type, std::forward<THead>(head).setCallback_([ctx](Try<ValueType>&& t) {
sizeof...(Ts) - sizeof...(TTail) - 1>(t); ctx->template setPartialResult<
ValueType,
sizeof...(Ts) - sizeof...(TTail)-1>(t);
}); });
// template tail-recursion // template tail-recursion
collectVariadicHelper(ctx, std::forward<TTail>(tail)...); collectVariadicHelper(ctx, std::forward<TTail>(tail)...);
......
...@@ -148,7 +148,7 @@ inline Future<Unit> via( ...@@ -148,7 +148,7 @@ inline Future<Unit> via(
/// easier to read and slightly more efficient. /// easier to read and slightly more efficient.
template <class Func> template <class Func>
auto via(Executor*, Func&& func) auto via(Executor*, Func&& func)
-> Future<typename isFuture<decltype(func())>::Inner>; -> Future<typename isFuture<decltype(std::declval<Func>()())>::Inner>;
/** When all the input Futures complete, the returned Future will complete. /** When all the input Futures complete, the returned Future will complete.
Errors do not cause early termination; this Future will always succeed Errors do not cause early termination; this Future will always succeed
......
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