#pragma once
-#include "folly/wangle/Executor.h"
-#include "folly/wangle/Future.h"
-#include "folly/Optional.h"
+#include <folly/wangle/Executor.h>
+#include <folly/wangle/Future.h>
+#include <folly/Optional.h>
namespace folly { namespace wangle {
future_ = starter_.getFuture();
}
+template <class T>
+Later<T>::Later(Future<T>&& f) {
+ MoveWrapper<Future<T>> fw(std::move(f));
+ *this = Later<void>()
+ .then([fw](Try<void>&&) mutable {
+ return std::move(*fw);
+ });
+}
+
template <typename T>
Later<T>::Later(Promise<void>&& starter)
: starter_(std::forward<Promise<void>>(starter)) { }
});
}
+template <typename T>
+Later<T>::Later(std::exception_ptr const& eptr) {
+ folly::MoveWrapper<Promise<T>> promise;
+ future_ = promise->getFuture();
+ starter_.getFuture().then([=](Try<void>&& t) mutable {
+ promise->setException(eptr);
+ });
+}
+
+template <typename T>
+template <typename E, class Unused>
+Later<T>::Later(E const& e) :
+ Later<T>::Later(std::make_exception_ptr<E>(e)) {
+}
+
+template <class T>
+template <class U, class Unused, class Unused2>
+Later<T>::Later(std::function<void(std::function<void(U&&)>&&)>&& fn) {
+ folly::MoveWrapper<Promise<U>> promise;
+ future_ = promise->getFuture();
+ starter_.getFuture().then([=](Try<void>&& t) mutable {
+ fn([=](U&& output) mutable {
+ promise->setValue(std::move(output));
+ });
+ });
+}
+
template <class T>
template <class F>
typename std::enable_if<
template <class T>
Later<T> Later<T>::via(Executor* executor) {
- Promise<T> promise;
+ folly::MoveWrapper<Promise<T>> promise;
Later<T> later(std::move(starter_));
- later.future_ = promise.getFuture();
- future_->executeWith(executor, std::move(promise));
+ later.future_ = promise->getFuture();
+
+ future_->setCallback_([executor, promise](Try<T>&& t) mutable {
+ folly::MoveWrapper<Try<T>> tt(std::move(t));
+ executor->add([promise, tt]() mutable {
+ promise->fulfilTry(std::move(*tt));
+ });
+ });
+
return later;
}
}
template <class T>
-void Later<T>::fireAndForget() {
- future_->setContinuation([] (Try<T>&& t) {}); // detach
- starter_.setValue();
+Later<std::vector<Try<T>>> whenAllLater(std::vector<Later<T>>&& laters) {
+ if (laters.size() == 0) {
+ return Later<std::vector<Try<T>>>(std::vector<Try<T>>());
+ }
+
+ auto ctx = new detail::WhenAllLaterContext<T>();
+ ctx->total = laters.size();
+ ctx->results.resize(ctx->total);
+
+ MoveWrapper<std::vector<Later<T>>> mlaters{std::move(laters)};
+
+ std::function<void(std::function<void(std::vector<Try<T>>&&)>&&)> wrapper =
+ [ctx, mlaters](std::function<void(std::vector<Try<T>>&&)>&& fn) mutable {
+ ctx->fn = std::move(fn);
+ size_t i = 0;
+ for (auto& l : *mlaters) {
+ l.then([ctx, i](Try<T>&& t) {
+ ctx->results[i] = std::move(t);
+ if (++ctx->count == ctx->total) {
+ ctx->fn(std::move(ctx->results));
+ delete ctx;
+ }
+ }).launch();
+ ++i;
+ }
+ };
+ return Later<std::vector<Try<T>>>(std::move(wrapper));
}
}}