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.
23 #include <type_traits>
25 #include "folly/MoveWrapper.h"
29 namespace folly { namespace wangle {
31 template <typename T> struct isFuture;
39 Future(Future const&) = delete;
40 Future& operator=(Future const&) = delete;
44 Future& operator=(Future&&);
48 /** Return the reference to result. Should not be called if !isReady().
49 Will rethrow the exception if an exception has been
52 This function is not thread safe - the returned Future can only
53 be executed from the thread that the executor runs it in.
54 See below for a thread safe version
56 typename std::add_lvalue_reference<T>::type
58 typename std::add_lvalue_reference<const T>::type
61 /// Returns a future which will call back on the other side of executor.
63 /// f.via(e).then(a); // safe
65 /// f.via(e).then(a).then(b); // faux pas
67 /// a will definitely execute in the intended thread, but b may execute
68 /// either in that thread, or in the current thread. If you need to
69 /// guarantee where b executes, use a Later.
70 template <typename Executor>
71 Future<T> via(Executor* executor);
73 /// Deprecated alias for via
74 template <typename Executor>
75 Future<T> executeWithSameThread(Executor* executor) {
80 Thread-safe version of executeWith
82 Since an executor would likely start executing the Future chain
83 right away, it would be a race condition to call:
84 Future.executeWith(...).then(...), as there would be race
85 condition between the then and the running Future.
86 Instead, you may pass in a Promise so that we can set up
87 the rest of the chain in advance, without any racey
88 modifications of the continuation
90 Deprecated. Use a Later.
92 template <typename Executor>
93 void executeWith(Executor* executor, Promise<T>&& cont_promise);
95 /** True when the result (or exception) is ready. */
98 /** A reference to the Try of the value */
101 /** When this Future has completed, execute func which is a function that
102 takes a Try<T>&&. A Future for the return type of func is
105 Future<string> f2 = f1.then([](Try<T>&&) { return string("foo"); });
107 The Future given to the functor is ready, and the functor may call
108 value(), which may rethrow if this has captured an exception. If func
109 throws, the exception will be captured in the Future that is returned.
111 /* TODO n3428 and other async frameworks have something like then(scheduler,
112 Future), we probably want to support a similar API (instead of
115 typename std::enable_if<
116 !isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
117 Future<typename std::result_of<F(Try<T>&&)>::type> >::type
120 /// Variant where func returns a Future<T> instead of a T. e.g.
122 /// Future<string> f2 = f1.then(
123 /// [](Try<T>&&) { return makeFuture<string>("foo"); });
125 typename std::enable_if<
126 isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
127 Future<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
130 /// Variant where func is an ordinary function (static method, method)
132 /// R doWork(Try<T>&&);
134 /// Future<R> f2 = f1.then(doWork);
139 /// static R doWork(Try<T>&&); }
141 /// Future<R> f2 = f1.then(&Worker::doWork);
142 template <class = T, class R = std::nullptr_t>
143 typename std::enable_if<!isFuture<R>::value, Future<R>>::type
144 inline then(R(*func)(Try<T>&&)) {
145 return then([func](Try<T>&& t) {
146 return (*func)(std::move(t));
150 /// Variant where func returns a Future<R> instead of a R. e.g.
153 /// Future<R> doWork(Try<T>&&); }
155 /// Future<R> f2 = f1.then(&Worker::doWork);
156 template <class = T, class R = std::nullptr_t>
157 typename std::enable_if<isFuture<R>::value, R>::type
158 inline then(R(*func)(Try<T>&&)) {
159 return then([func](Try<T>&& t) {
160 return (*func)(std::move(t));
164 /// Variant where func is an member function
167 /// R doWork(Try<T>&&); }
170 /// Future<R> f2 = f1.then(w, &Worker::doWork);
171 template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
172 typename std::enable_if<!isFuture<R>::value, Future<R>>::type
173 inline then(Caller *instance, R(Caller::*func)(Try<T>&&)) {
174 return then([instance, func](Try<T>&& t) {
175 return (instance->*func)(std::move(t));
179 /// Variant where func returns a Future<R> instead of a R. e.g.
182 /// Future<R> doWork(Try<T>&&); }
185 /// Future<R> f2 = f1.then(w, &Worker::doWork);
186 template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
187 typename std::enable_if<isFuture<R>::value, R>::type
188 inline then(Caller *instance, R(Caller::*func)(Try<T>&&)) {
189 return then([instance, func](Try<T>&& t) {
190 return (instance->*func)(std::move(t));
194 /// Convenience method for ignoring the value and creating a Future<void>.
195 /// Exceptions still propagate.
198 /// Use of this method is advanced wizardry.
199 /// XXX should this be protected?
201 void setContinuation(F&& func);
204 typedef detail::FutureObject<T>* objPtr;
206 // shared state object
210 Future(objPtr obj) : obj_(obj) {}
212 void throwIfInvalid() const;
214 friend class Promise<T>;
218 Make a completed Future by moving in a value. e.g.
221 auto f = makeFuture(std::move(foo));
225 auto f = makeFuture<string>("foo");
228 Future<typename std::decay<T>::type> makeFuture(T&& t);
230 /** Make a completed void Future. */
231 Future<void> makeFuture();
233 /** Make a completed Future by executing a function. If the function throws
234 we capture the exception, otherwise we capture the result. */
238 typename std::enable_if<
239 !std::is_reference<F>::value, bool>::type sdf = false)
240 -> Future<decltype(func())>;
245 -> Future<decltype(func())>;
247 /// Make a failed Future from an exception_ptr.
248 /// Because the Future's type cannot be inferred you have to specify it, e.g.
250 /// auto f = makeFuture<string>(std::current_exception());
252 Future<T> makeFuture(std::exception_ptr const& e);
254 /** Make a Future from an exception type E that can be passed to
255 std::make_exception_ptr(). */
256 template <class T, class E>
257 typename std::enable_if<std::is_base_of<std::exception, E>::value, Future<T>>::type
258 makeFuture(E const& e);
260 /** When all the input Futures complete, the returned Future will complete.
261 Errors do not cause early termination; this Future will always succeed
262 after all its Futures have finished (whether successfully or with an
265 The Futures are moved in, so your copies are invalid. If you need to
266 chain further from these Futures, use the variant with an output iterator.
268 XXX is this still true?
269 This function is thread-safe for Futures running on different threads.
271 The return type for Future<T> input is a Future<std::vector<Try<T>>>
273 template <class InputIterator>
274 Future<std::vector<Try<
275 typename std::iterator_traits<InputIterator>::value_type::value_type>>>
276 whenAll(InputIterator first, InputIterator last);
278 /// This version takes a varying number of Futures instead of an iterator.
279 /// The return type for (Future<T1>, Future<T2>, ...) input
280 /// is a Future<std::tuple<Try<T1>, Try<T2>, ...>>.
281 /// The Futures are moved in, so your copies are invalid.
282 template <typename... Fs>
283 typename detail::VariadicContext<
284 typename std::decay<Fs>::type::value_type...>::type
287 /** The result is a pair of the index of the first Future to complete and
288 the Try. If multiple Futures complete at the same time (or are already
289 complete when passed in), the "winner" is chosen non-deterministically.
291 This function is thread-safe for Futures running on different threads.
293 template <class InputIterator>
296 Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
297 whenAny(InputIterator first, InputIterator last);
299 /** when n Futures have completed, the Future completes with a vector of
300 the index and Try of those n Futures (the indices refer to the original
301 order, but the result vector will be in an arbitrary order)
305 template <class InputIterator>
306 Future<std::vector<std::pair<
308 Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>>
309 whenN(InputIterator first, InputIterator last, size_t n);
313 #include "Future-inl.h"