From a9c6c80d31f8a035bf4d7ef729956a8e110ef777 Mon Sep 17 00:00:00 2001 From: Hannes Roth Date: Thu, 30 Apr 2015 18:38:27 -0700 Subject: [PATCH] (Wangle) Simplify reduce, use the same implementation for func returning T/Future Summary: I wanted to use `collectAll` for `reduce` if `func` does not return a Future, because the overhead seemed smaller, but it has been suggested that running the callback as soon as possible might be better. Not sure which is. Note that this also makes n copies of the lambda and moves the value at least n times. I also plan to add a `streamingReduce` which calls `func` as soon as results come in (but out of order). Test Plan: Run all the tests. Reviewed By: hans@fb.com Subscribers: folly-diffs@, jsedgwick, yfeldblum, chalfant FB internal diff: D2015316 Tasks: 6025252 Signature: t1:2015316:1430349611:4f62a540ded85299a22670dd2add27cf1458e8f8 --- folly/futures/Future-inl.h | 38 +++++++++++--------------------------- folly/futures/Future.h | 1 - folly/futures/helpers.h | 16 ++++------------ 3 files changed, 15 insertions(+), 40 deletions(-) diff --git a/folly/futures/Future-inl.h b/folly/futures/Future-inl.h index 00cfba22..39ac14b4 100644 --- a/folly/futures/Future-inl.h +++ b/folly/futures/Future-inl.h @@ -782,44 +782,28 @@ collectN(InputIterator first, InputIterator last, size_t n) { return ctx->p.getFuture(); } -template -typename std::enable_if::value, Future>::type -reduce(It first, It last, T initial, F func) { +template +Future reduce(It first, It last, T&& initial, F&& func) { if (first == last) { return makeFuture(std::move(initial)); } + typedef typename std::iterator_traits::value_type::value_type ItT; + typedef typename std::conditional< + detail::callableWith&&>::value, Try, ItT>::type Arg; typedef isTry IsTry; - return collectAll(first, last) - .then([initial, func](std::vector>& vals) mutable { - for (auto& val : vals) { - initial = func(std::move(initial), - // Either return a ItT&& or a Try&& depending - // on the type of the argument of func. - val.template get()); - } - return initial; - }); -} - -template -typename std::enable_if::value, Future>::type -reduce(It first, It last, T initial, F func) { - if (first == last) { - return makeFuture(std::move(initial)); - } - - typedef isTry IsTry; + folly::MoveWrapper minitial(std::move(initial)); + auto sfunc = std::make_shared(std::move(func)); - auto f = first->then([initial, func](Try& head) mutable { - return func(std::move(initial), + auto f = first->then([minitial, sfunc](Try& head) mutable { + return (*sfunc)(std::move(*minitial), head.template get()); }); for (++first; first != last; ++first) { - f = collectAll(f, *first).then([func](std::tuple, Try>& t) { - return func(std::move(std::get<0>(t).value()), + f = collectAll(f, *first).then([sfunc](std::tuple, Try>& t) { + return (*sfunc)(std::move(std::get<0>(t).value()), // Either return a ItT&& or a Try&& depending // on the type of the argument of func. std::get<1>(t).template get()); diff --git a/folly/futures/Future.h b/folly/futures/Future.h index 06572c63..01e734e6 100644 --- a/folly/futures/Future.h +++ b/folly/futures/Future.h @@ -407,7 +407,6 @@ class Future { void setExecutor(Executor* x) { core_->setExecutor(x); } }; - } // folly #include diff --git a/folly/futures/helpers.h b/folly/futures/helpers.h index c39d6686..97c418d1 100644 --- a/folly/futures/helpers.h +++ b/folly/futures/helpers.h @@ -235,22 +235,14 @@ using isFutureResult = isFuture::type>; Func can either return a T, or a Future */ -template ::value_type::value_type, - class Arg = MaybeTryArg> -typename std::enable_if::value, Future>::type -reduce(It first, It last, T initial, F func); - -template ::value_type::value_type, - class Arg = MaybeTryArg> -typename std::enable_if::value, Future>::type -reduce(It first, It last, T initial, F func); +template +Future reduce(It first, It last, T&& initial, F&& func); /// Sugar for the most common case template auto reduce(Collection&& c, T&& initial, F&& func) - -> decltype(reduce(c.begin(), c.end(), initial, func)) { + -> decltype(reduce(c.begin(), c.end(), std::forward(initial), + std::forward(func))) { return reduce( c.begin(), c.end(), -- 2.34.1