*/
#pragma once
-#include <folly/futures/Future.h>
+#include <atomic>
+#include <tuple>
+#include <utility>
+
#include <folly/Portability.h>
+#include <folly/Try.h>
+#include <folly/futures/Future.h>
+#include <folly/futures/Promise.h>
namespace folly {
+namespace detail {
+template <typename... Ts>
+struct CollectAllVariadicContext {
+ CollectAllVariadicContext() {}
+ template <typename T, size_t I>
+ inline void setPartialResult(Try<T>& t) {
+ std::get<I>(results) = std::move(t);
+ }
+ ~CollectAllVariadicContext() {
+ p.setValue(std::move(results));
+ }
+ Promise<std::tuple<Try<Ts>...>> p;
+ std::tuple<Try<Ts>...> results;
+ typedef Future<std::tuple<Try<Ts>...>> type;
+};
+
+template <typename... Ts>
+struct CollectVariadicContext {
+ CollectVariadicContext() {}
+ template <typename T, size_t I>
+ inline void setPartialResult(Try<T>& t) {
+ if (t.hasException()) {
+ if (!threw.exchange(true)) {
+ p.setException(std::move(t.exception()));
+ }
+ } else if (!threw) {
+ std::get<I>(results) = std::move(t);
+ }
+ }
+ ~CollectVariadicContext() noexcept {
+ if (!threw.exchange(true)) {
+ p.setValue(unwrapTryTuple(std::move(results)));
+ }
+ }
+ Promise<std::tuple<Ts...>> p;
+ std::tuple<folly::Try<Ts>...> results;
+ std::atomic<bool> threw{false};
+ typedef Future<std::tuple<Ts...>> type;
+};
+}
+
/// 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
/// depend on the template type (rather, on the type of their arguments in