2 * Copyright 2014 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "folly/wangle/Executor.h"
20 #include "folly/wangle/Future.h"
21 #include "folly/Optional.h"
23 namespace folly { namespace wangle {
27 static const bool value = false;
31 struct isLater<Later<T> > {
32 static const bool value = true;
36 struct isLaterOrFuture {
37 static const bool value = false;
41 struct isLaterOrFuture<Later<T>> {
42 static const bool value = true;
46 struct isLaterOrFuture<Future<T>> {
47 static const bool value = true;
51 template <class U, class Unused, class Unused2>
53 future_ = starter_.getFuture();
57 Later<T>::Later(Promise<void>&& starter)
58 : starter_(std::forward<Promise<void>>(starter)) { }
61 template <class U, class Unused, class Unused2>
62 Later<T>::Later(U&& input) {
63 folly::MoveWrapper<Promise<U>> promise;
64 folly::MoveWrapper<U> inputm(std::forward<U>(input));
65 future_ = promise->getFuture();
66 starter_.getFuture().then([=](Try<void>&& t) mutable {
67 promise->setValue(std::move(*inputm));
72 template <class U, class Unused, class Unused2>
73 Later<T>::Later(std::function<void(std::function<void(U&&)>&&)>&& fn) {
74 folly::MoveWrapper<Promise<U>> promise;
75 future_ = promise->getFuture();
76 starter_.getFuture().then([=](Try<void>&& t) mutable {
77 fn([=](U&& output) mutable {
78 promise->setValue(std::move(output));
85 typename std::enable_if<
86 !isLaterOrFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
87 Later<typename std::result_of<F(Try<T>&&)>::type> >::type
88 Later<T>::then(F&& fn) {
89 typedef typename std::result_of<F(Try<T>&&)>::type B;
91 Later<B> later(std::move(starter_));
92 later.future_ = future_->then(std::forward<F>(fn));
98 typename std::enable_if<
99 isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
100 Later<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
101 Later<T>::then(F&& fn) {
102 typedef typename std::result_of<F(Try<T>&&)>::type::value_type B;
104 Later<B> later(std::move(starter_));
105 later.future_ = future_->then(std::move(fn));
111 typename std::enable_if<
112 isLater<typename std::result_of<F(Try<T>&&)>::type>::value,
113 Later<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
114 Later<T>::then(F&& fn) {
115 typedef typename std::result_of<F(Try<T>&&)>::type::value_type B;
117 folly::MoveWrapper<Promise<B>> promise;
118 folly::MoveWrapper<F> fnm(std::move(fn));
119 Later<B> later(std::move(starter_));
120 later.future_ = promise->getFuture();
121 future_->then([=](Try<T>&& t) mutable {
123 .then([=](Try<B>&& t2) mutable {
124 promise->fulfilTry(std::move(t2));
132 Later<T> Later<T>::via(Executor* executor) {
134 Later<T> later(std::move(starter_));
135 later.future_ = promise.getFuture();
136 future_->executeWith(executor, std::move(promise));
141 Future<T> Later<T>::launch() {
143 return std::move(*future_);