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(Future<T>&& f) {
58 MoveWrapper<Future<T>> fw(std::move(f));
60 .then([fw](Try<void>&&) mutable {
61 return std::move(*fw);
66 Later<T>::Later(Promise<void>&& starter)
67 : starter_(std::forward<Promise<void>>(starter)) { }
70 template <class U, class Unused, class Unused2>
71 Later<T>::Later(U&& input) {
72 folly::MoveWrapper<Promise<U>> promise;
73 folly::MoveWrapper<U> inputm(std::forward<U>(input));
74 future_ = promise->getFuture();
75 starter_.getFuture().then([=](Try<void>&& t) mutable {
76 promise->setValue(std::move(*inputm));
81 Later<T>::Later(std::exception_ptr const& eptr) {
82 folly::MoveWrapper<Promise<T>> promise;
83 future_ = promise->getFuture();
84 starter_.getFuture().then([=](Try<void>&& t) mutable {
85 promise->setException(eptr);
90 template <typename E, class Unused>
91 Later<T>::Later(E const& e) :
92 Later<T>::Later(std::make_exception_ptr<E>(e)) {
96 template <class U, class Unused, class Unused2>
97 Later<T>::Later(std::function<void(std::function<void(U&&)>&&)>&& fn) {
98 folly::MoveWrapper<Promise<U>> promise;
99 future_ = promise->getFuture();
100 starter_.getFuture().then([=](Try<void>&& t) mutable {
101 fn([=](U&& output) mutable {
102 promise->setValue(std::move(output));
109 typename std::enable_if<
110 !isLaterOrFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
111 Later<typename std::result_of<F(Try<T>&&)>::type> >::type
112 Later<T>::then(F&& fn) {
113 typedef typename std::result_of<F(Try<T>&&)>::type B;
115 Later<B> later(std::move(starter_));
116 later.future_ = future_->then(std::forward<F>(fn));
122 typename std::enable_if<
123 isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
124 Later<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
125 Later<T>::then(F&& fn) {
126 typedef typename std::result_of<F(Try<T>&&)>::type::value_type B;
128 Later<B> later(std::move(starter_));
129 later.future_ = future_->then(std::move(fn));
135 typename std::enable_if<
136 isLater<typename std::result_of<F(Try<T>&&)>::type>::value,
137 Later<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
138 Later<T>::then(F&& fn) {
139 typedef typename std::result_of<F(Try<T>&&)>::type::value_type B;
141 folly::MoveWrapper<Promise<B>> promise;
142 folly::MoveWrapper<F> fnm(std::move(fn));
143 Later<B> later(std::move(starter_));
144 later.future_ = promise->getFuture();
145 future_->then([=](Try<T>&& t) mutable {
147 .then([=](Try<B>&& t2) mutable {
148 promise->fulfilTry(std::move(t2));
156 Later<T> Later<T>::via(Executor* executor) {
157 folly::MoveWrapper<Promise<T>> promise;
158 Later<T> later(std::move(starter_));
159 later.future_ = promise->getFuture();
161 future_->setCallback_([executor, promise](Try<T>&& t) mutable {
162 folly::MoveWrapper<Try<T>> tt(std::move(t));
163 executor->add([promise, tt]() mutable {
164 promise->fulfilTry(std::move(*tt));
172 Future<T> Later<T>::launch() {
174 return std::move(*future_);