class Result = decltype(std::declval<ItT>().then(std::declval<F>()))>
std::vector<Future<Result>> map(It first, It last, F func);
+ // Sugar for the most common case
+ template <class Collection, class F>
+ auto map(Collection&& c, F&& func)
+ -> decltype(map(c.begin(), c.end(), func)) {
+ return map(c.begin(), c.end(), std::forward<F>(func));
+ }
+
}
template <class T>
typename std::iterator_traits<InputIterator>::value_type::value_type>>>
collectAll(InputIterator first, InputIterator last);
+// Sugar for the most common case
+template <class Collection>
+auto collectAll(Collection&& c) -> decltype(collectAll(c.begin(), c.end())) {
+ return collectAll(c.begin(), c.end());
+}
+
/// This version takes a varying number of Futures instead of an iterator.
/// The return type for (Future<T1>, Future<T2>, ...) input
/// is a Future<std::tuple<Try<T1>, Try<T2>, ...>>.
>::result_type>
collect(InputIterator first, InputIterator last);
+// Sugar for the most common case
+template <class Collection>
+auto collect(Collection&& c) -> decltype(collect(c.begin(), c.end())) {
+ return collect(c.begin(), c.end());
+}
+
/** The result is a pair of the index of the first Future to complete and
the Try. If multiple Futures complete at the same time (or are already
complete when passed in), the "winner" is chosen non-deterministically.
Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
collectAny(InputIterator first, InputIterator last);
+// Sugar for the most common case
+template <class Collection>
+auto collectAny(Collection&& c) -> decltype(collectAny(c.begin(), c.end())) {
+ return collectAny(c.begin(), c.end());
+}
+
/** when n Futures have completed, the Future completes with a vector of
the index and Try of those n Futures (the indices refer to the original
order, but the result vector will be in an arbitrary order)
Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>>
collectN(InputIterator first, InputIterator last, size_t n);
+// Sugar for the most common case
+template <class Collection>
+auto collectN(Collection&& c, size_t n)
+ -> decltype(collectN(c.begin(), c.end(), n)) {
+ return collectN(c.begin(), c.end(), n);
+}
+
template <typename F, typename T, typename ItT>
using MaybeTryArg = typename std::conditional<
detail::callableWith<F, T&&, Try<ItT>&&>::value, Try<ItT>, ItT>::type;
typename std::enable_if<isFutureResult<F, T, Arg>::value, Future<T>>::type
reduce(It first, It last, T initial, F func);
+// Sugar for the most common case
+template <class Collection, class T, class F>
+auto reduce(Collection&& c, T&& initial, F&& func)
+ -> decltype(reduce(c.begin(), c.end(), initial, func)) {
+ return reduce(
+ c.begin(),
+ c.end(),
+ std::forward<T>(initial),
+ std::forward<F>(func));
+}
+
} // folly
#include <folly/futures/Future-inl.h>
for (auto& p : promises)
futures.push_back(p.getFuture());
- auto allf = collectAll(futures.begin(), futures.end());
+ auto allf = collectAll(futures);
random_shuffle(promises.begin(), promises.end());
for (auto& p : promises) {
for (auto& p : promises)
futures.push_back(p.getFuture());
- auto allf = collectAll(futures.begin(), futures.end());
+ auto allf = collectAll(futures);
promises[0].setValue(42);
for (auto& p : promises)
futures.push_back(p.getFuture());
- auto allf = collectAll(futures.begin(), futures.end())
+ auto allf = collectAll(futures)
.then([](Try<vector<Try<void>>>&& ts) {
for (auto& f : ts.value())
f.value();
for (auto& p : promises)
futures.push_back(p.getFuture());
- auto allf = collect(futures.begin(), futures.end());
+ auto allf = collect(futures);
random_shuffle(promises.begin(), promises.end());
for (auto& p : promises) {
for (auto& p : promises)
futures.push_back(p.getFuture());
- auto allf = collect(futures.begin(), futures.end());
+ auto allf = collect(futures);
random_shuffle(promises.begin(), promises.end());
for (int i = 0; i < 10; i++) {
for (auto& p : promises)
futures.push_back(p.getFuture());
- auto allf = collect(futures.begin(), futures.end());
+ auto allf = collect(futures);
random_shuffle(promises.begin(), promises.end());
for (auto& p : promises) {
for (auto& p : promises)
futures.push_back(p.getFuture());
- auto allf = collect(futures.begin(), futures.end());
+ auto allf = collect(futures);
random_shuffle(promises.begin(), promises.end());
for (int i = 0; i < 10; i++) {
for (auto& p : promises)
futures.push_back(p.getFuture());
- collect(futures.begin(), futures.end());
+ collect(futures);
}
}
for (auto& p : promises)
futures.push_back(p.getFuture());
- auto allf = collect(futures.begin(), futures.end());
+ auto allf = collect(futures);
for (auto i : indices) {
EXPECT_FALSE(allf.isReady());
EXPECT_FALSE(f.isReady());
}
- auto anyf = collectAny(futures.begin(), futures.end());
+ auto anyf = collectAny(futures);
/* futures were moved in, so these are invalid now */
EXPECT_FALSE(anyf.isReady());
EXPECT_FALSE(f.isReady());
}
- auto anyf = collectAny(futures.begin(), futures.end());
+ auto anyf = collectAny(futures);
EXPECT_FALSE(anyf.isReady());
for (auto& p : promises)
futures.push_back(p.getFuture());
- auto anyf = collectAny(futures.begin(), futures.end())
+ auto anyf = collectAny(futures)
.then([](pair<size_t, Try<int>> p) {
EXPECT_EQ(42, p.second.value());
});
for (int i = 0; i < 10; i++)
fs.push_back(makeFuture());
- collectAll(fs.begin(), fs.end())
+ collectAll(fs)
.then([&](vector<Try<void>> ts) {
EXPECT_EQ(fs.size(), ts.size());
});
for (int i = 0; i < 10; i++)
fs.push_back(makeFuture(i));
- collectAny(fs.begin(), fs.end())
+ collectAny(fs)
.then([&](pair<size_t, Try<int>> p) {
EXPECT_EQ(p.first, p.second.value());
});
bool flag = false;
size_t n = 3;
- collectN(futures.begin(), futures.end(), n)
+ collectN(futures, n)
.then([&](vector<pair<size_t, Try<void>>> v) {
flag = true;
EXPECT_EQ(n, v.size());
for (int i = 0; i < 10; i++)
futures.push_back(makeFuture());
- auto anyf = collectAny(futures.begin(), futures.end());
+ auto anyf = collectAny(futures);
}
{
for (int i = 0; i < 10; i++)
futures.push_back(makeFuture());
- auto allf = collectAll(futures.begin(), futures.end());
+ auto allf = collectAll(futures);
}
}
TEST(Future, collectAll_none) {
vector<Future<int>> fs;
- auto f = collectAll(fs.begin(), fs.end());
+ auto f = collectAll(fs);
EXPECT_TRUE(f.isReady());
}
vector<Future<void>> v_f;
v_f.push_back(makeFuture());
v_f.push_back(makeFuture());
- auto done_v_f = collectAll(v_f.begin(), v_f.end()).wait().value();
+ auto done_v_f = collectAll(v_f).wait().value();
EXPECT_EQ(2, done_v_f.size());
vector<Future<bool>> v_fb;
v_fb.push_back(makeFuture(true));
v_fb.push_back(makeFuture(false));
- auto fut = collectAll(v_fb.begin(), v_fb.end());
+ auto fut = collectAll(v_fb);
auto done_v_fb = std::move(fut.wait().value());
EXPECT_EQ(2, done_v_fb.size());
}
vector<Future<bool>> v_fb;
v_fb.push_back(makeFuture(true));
v_fb.push_back(makeFuture(false));
- auto f = collectAll(v_fb.begin(), v_fb.end());
+ auto f = collectAll(v_fb);
f.wait(milliseconds(1));
EXPECT_TRUE(f.isReady());
EXPECT_EQ(2, f.value().size());
Promise<bool> p2;
v_fb.push_back(p1.getFuture());
v_fb.push_back(p2.getFuture());
- auto f = collectAll(v_fb.begin(), v_fb.end());
+ auto f = collectAll(v_fb);
f.wait(milliseconds(1));
EXPECT_FALSE(f.isReady());
p1.setValue(true);
for (auto& p : *promises) p.setValue();
});
- return collectAll(futures.begin(), futures.end());
+ return collectAll(futures);
};
fn().wait();
{
auto fs = makeFutures(0);
- Future<double> f1 = reduce(fs.begin(), fs.end(), 1.2,
+ Future<double> f1 = reduce(fs, 1.2,
[](double a, Try<int>&& b){
return a + *b + 0.1;
});
{
auto fs = makeFutures(1);
- Future<double> f1 = reduce(fs.begin(), fs.end(), 0.0,
+ Future<double> f1 = reduce(fs, 0.0,
[](double a, Try<int>&& b){
return a + *b + 0.1;
});
{
auto fs = makeFutures(3);
- Future<double> f1 = reduce(fs.begin(), fs.end(), 0.0,
+ Future<double> f1 = reduce(fs, 0.0,
[](double a, Try<int>&& b){
return a + *b + 0.1;
});
{
auto fs = makeFutures(3);
- Future<double> f1 = reduce(fs.begin(), fs.end(), 0.0,
+ Future<double> f1 = reduce(fs, 0.0,
[](double a, int&& b){
return a + b + 0.1;
});
{
auto fs = makeFutures(3);
- Future<double> f2 = reduce(fs.begin(), fs.end(), 0.0,
+ Future<double> f2 = reduce(fs, 0.0,
[](double a, Try<int>&& b){
return makeFuture<double>(a + *b + 0.1);
});
{
auto fs = makeFutures(3);
- Future<double> f2 = reduce(fs.begin(), fs.end(), 0.0,
+ Future<double> f2 = reduce(fs, 0.0,
[](double a, int&& b){
return makeFuture<double>(a + b + 0.1);
});
fs.push_back(p3.getFuture());
int c = 0;
- auto fs2 = futures::map(fs.begin(), fs.end(), [&](int i){
+ auto fs2 = futures::map(fs, [&](int i){
c += i;
});
p1.setValue(1);
EXPECT_EQ(3, c);
- EXPECT_TRUE(collect(fs2.begin(), fs2.end()).isReady());
+ EXPECT_TRUE(collect(fs2).isReady());
}