Really fix the clang warning in Format-inl.h
[folly.git] / folly / wangle / Later-inl.h
index e17f2d7eedd08e9a8d857d694ac4a6a8d521efc2..b054d6d54209e0ec70125f01d959471f95fc8324 100644 (file)
@@ -16,9 +16,9 @@
 
 #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 {
 
@@ -53,6 +53,15 @@ Later<T>::Later() {
   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)) { }
@@ -68,6 +77,33 @@ Later<T>::Later(U&& input) {
   });
 }
 
+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<
@@ -118,10 +154,17 @@ Later<T>::then(F&& fn) {
 
 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;
 }
 
@@ -132,9 +175,33 @@ Future<T> Later<T>::launch() {
 }
 
 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));
 }
 
 }}