namespace detail {
+template <class, class, typename = void> struct CollectContextHelper;
+
+template <class T, class VecT>
+struct CollectContextHelper<T, VecT,
+ typename std::enable_if<std::is_same<T, VecT>::value>::type> {
+ static inline std::vector<T>& getResults(std::vector<VecT>& results) {
+ return results;
+ }
+};
+
+template <class T, class VecT>
+struct CollectContextHelper<T, VecT,
+ typename std::enable_if<!std::is_same<T, VecT>::value>::type> {
+ static inline std::vector<T> getResults(std::vector<VecT>& results) {
+ std::vector<T> finalResults;
+ finalResults.reserve(results.size());
+ for (auto& opt : results) {
+ finalResults.push_back(std::move(opt.value()));
+ }
+ return finalResults;
+ }
+};
+
template <typename T>
struct CollectContext {
- explicit CollectContext(int n) : count(0), threw(false) {}
+
+ typedef typename std::conditional<
+ std::is_default_constructible<T>::value,
+ T,
+ Optional<T>
+ >::type VecT;
+
+ explicit CollectContext(int n) : count(0), threw(false) {
+ results.resize(n);
+ }
Promise<std::vector<T>> p;
- std::vector<T> results;
+ std::vector<VecT> results;
std::atomic<size_t> count;
std::atomic_bool threw;
}
inline void setValue() {
- p.setValue(std::move(results));
+ p.setValue(CollectContextHelper<T, VecT>::getResults(results));
}
inline void addResult(int i, Try<T>& t) {
template <>
struct CollectContext<void> {
+
explicit CollectContext(int n) : count(0), threw(false) {}
+
Promise<void> p;
std::atomic<size_t> count;
std::atomic_bool threw;
}
}
+struct NotDefaultConstructible {
+ NotDefaultConstructible() = delete;
+ NotDefaultConstructible(int arg) : i(arg) {}
+ int i;
+};
+
+// We have a specialized implementation for non-default-constructible objects
+// Ensure that it works and preserves order
+TEST(Future, collectNotDefaultConstructible) {
+ vector<Promise<NotDefaultConstructible>> promises(10);
+ vector<Future<NotDefaultConstructible>> futures;
+ vector<int> indices(10);
+ std::iota(indices.begin(), indices.end(), 0);
+ random_shuffle(indices.begin(), indices.end());
+
+ for (auto& p : promises)
+ futures.push_back(p.getFuture());
+
+ auto allf = collect(futures.begin(), futures.end());
+
+ for (auto i : indices) {
+ EXPECT_FALSE(allf.isReady());
+ promises[i].setValue(NotDefaultConstructible(i));
+ }
+
+ EXPECT_TRUE(allf.isReady());
+ int i = 0;
+ for (auto val : allf.value()) {
+ EXPECT_EQ(i, val.i);
+ i++;
+ }
+}
+
TEST(Future, whenAny) {
{
vector<Promise<int>> promises(10);