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>
26 #include <folly/MoveWrapper.h>
27 #include <folly/wangle/Promise.h>
28 #include <folly/wangle/Try.h>
30 namespace folly { namespace wangle {
33 template <class> struct Core;
34 template <class...> struct VariadicContext;
38 typedef typename std::conditional<
39 std::is_same<T, void>::value,
45 template <class> struct Promise;
47 template <typename T> struct isFuture;
55 Future(Future const&) = delete;
56 Future& operator=(Future const&) = delete;
59 Future(Future&&) noexcept;
60 Future& operator=(Future&&);
64 /** Return the reference to result. Should not be called if !isReady().
65 Will rethrow the exception if an exception has been
68 This function is not thread safe - the returned Future can only
69 be executed from the thread that the executor runs it in.
70 See below for a thread safe version
72 typename std::add_lvalue_reference<T>::type
74 typename std::add_lvalue_reference<const T>::type
77 /// Returns an inactive Future which will call back on the other side of
78 /// executor (when it is activated).
80 /// NB remember that Futures activate when they destruct. This is good,
81 /// it means that this will work:
83 /// f.via(e).then(a).then(b);
85 /// a and b will execute in the same context (the far side of e), because
86 /// the Future (temporary variable) created by via(e) does not call back
87 /// until it destructs, which is after then(a) and then(b) have been wired
90 /// But this is still racy:
92 /// f = f.via(e).then(a);
94 template <typename Executor>
95 Future<T> via(Executor* executor);
97 /** True when the result (or exception) is ready. */
100 /** A reference to the Try of the value */
103 /** When this Future has completed, execute func which is a function that
104 takes a Try<T>&&. A Future for the return type of func is
107 Future<string> f2 = f1.then([](Try<T>&&) { return string("foo"); });
109 The Future given to the functor is ready, and the functor may call
110 value(), which may rethrow if this has captured an exception. If func
111 throws, the exception will be captured in the Future that is returned.
113 /* TODO n3428 and other async frameworks have something like then(scheduler,
114 Future), we might want to support a similar API which could be
115 implemented a little more efficiently than
116 f.via(executor).then(callback) */
118 typename std::enable_if<
119 !isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
120 Future<typename std::result_of<F(Try<T>&&)>::type> >::type
123 /// Variant where func takes a T directly, bypassing a try. Any exceptions
124 /// will be implicitly passed on to the resultant Future.
126 /// Future<int> f = makeFuture<int>(42).then([](int i) { return i+1; });
128 typename std::enable_if<
129 !std::is_same<T, void>::value &&
130 !isFuture<typename std::result_of<
131 F(typename detail::AliasIfVoid<T>::type&&)>::type>::value,
132 Future<typename std::result_of<
133 F(typename detail::AliasIfVoid<T>::type&&)>::type> >::type
136 /// Like the above variant, but for void futures. That is, func takes no
139 /// Future<int> f = makeFuture().then([] { return 42; });
141 typename std::enable_if<
142 std::is_same<T, void>::value &&
143 !isFuture<typename std::result_of<F()>::type>::value,
144 Future<typename std::result_of<F()>::type> >::type
147 /// Variant where func returns a Future<T> instead of a T. e.g.
149 /// Future<string> f2 = f1.then(
150 /// [](Try<T>&&) { return makeFuture<string>("foo"); });
152 typename std::enable_if<
153 isFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
154 Future<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
157 /// Variant where func returns a Future<T2> and takes a T directly, bypassing
158 /// a Try. Any exceptions will be implicitly passed on to the resultant
159 /// Future. For example,
161 /// Future<int> f = makeFuture<int>(42).then(
162 /// [](int i) { return makeFuture<int>(i+1); });
164 typename std::enable_if<
165 !std::is_same<T, void>::value &&
166 isFuture<typename std::result_of<
167 F(typename detail::AliasIfVoid<T>::type&&)>::type>::value,
168 Future<typename std::result_of<
169 F(typename detail::AliasIfVoid<T>::type&&)>::type::value_type> >::type
172 /// Like the above variant, but for void futures. That is, func takes no
173 /// argument and returns a future.
175 /// Future<int> f = makeFuture().then(
176 /// [] { return makeFuture<int>(42); });
178 typename std::enable_if<
179 std::is_same<T, void>::value &&
180 isFuture<typename std::result_of<F()>::type>::value,
181 Future<typename std::result_of<F()>::type::value_type> >::type
184 /// Variant where func is an ordinary function (static method, method)
186 /// R doWork(Try<T>&&);
188 /// Future<R> f2 = f1.then(doWork);
193 /// static R doWork(Try<T>&&); }
195 /// Future<R> f2 = f1.then(&Worker::doWork);
196 template <class = T, class R = std::nullptr_t>
197 typename std::enable_if<!isFuture<R>::value, Future<R>>::type
198 inline then(R(*func)(Try<T>&&)) {
199 return then([func](Try<T>&& t) {
200 return (*func)(std::move(t));
204 /// Variant where func returns a Future<R> instead of a R. e.g.
207 /// Future<R> doWork(Try<T>&&); }
209 /// Future<R> f2 = f1.then(&Worker::doWork);
210 template <class = T, class R = std::nullptr_t>
211 typename std::enable_if<isFuture<R>::value, R>::type
212 inline then(R(*func)(Try<T>&&)) {
213 return then([func](Try<T>&& t) {
214 return (*func)(std::move(t));
218 /// Variant where func is an member function
221 /// R doWork(Try<T>&&); }
224 /// Future<R> f2 = f1.then(w, &Worker::doWork);
225 template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
226 typename std::enable_if<!isFuture<R>::value, Future<R>>::type
227 inline then(Caller *instance, R(Caller::*func)(Try<T>&&)) {
228 return then([instance, func](Try<T>&& t) {
229 return (instance->*func)(std::move(t));
233 // Same as above, but func takes void instead of Try<void>&&
234 template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
235 typename std::enable_if<
236 std::is_same<T, void>::value && !isFuture<R>::value, Future<R>>::type
237 inline then(Caller *instance, R(Caller::*func)()) {
238 return then([instance, func]() {
239 return (instance->*func)();
243 // Same as above, but func takes T&& instead of Try<T>&&
244 template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
245 typename std::enable_if<
246 !std::is_same<T, void>::value && !isFuture<R>::value, Future<R>>::type
249 R(Caller::*func)(typename detail::AliasIfVoid<T>::type&&)) {
250 return then([instance, func](T&& t) {
251 return (instance->*func)(std::move(t));
255 /// Variant where func returns a Future<R> instead of a R. e.g.
258 /// Future<R> doWork(Try<T>&&); }
261 /// Future<R> f2 = f1.then(w, &Worker::doWork);
262 template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
263 typename std::enable_if<isFuture<R>::value, R>::type
264 inline then(Caller *instance, R(Caller::*func)(Try<T>&&)) {
265 return then([instance, func](Try<T>&& t) {
266 return (instance->*func)(std::move(t));
270 // Same as above, but func takes void instead of Try<void>&&
271 template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
272 typename std::enable_if<
273 std::is_same<T, void>::value && isFuture<R>::value, R>::type
274 inline then(Caller *instance, R(Caller::*func)()) {
275 return then([instance, func]() {
276 return (instance->*func)();
280 // Same as above, but func takes T&& instead of Try<T>&&
281 template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
282 typename std::enable_if<
283 !std::is_same<T, void>::value && isFuture<R>::value, R>::type
286 R(Caller::*func)(typename detail::AliasIfVoid<T>::type&&)) {
287 return then([instance, func](T&& t) {
288 return (instance->*func)(std::move(t));
292 /// Convenience method for ignoring the value and creating a Future<void>.
293 /// Exceptions still propagate.
296 /// This is not the method you're looking for.
298 /// This needs to be public because it's used by make* and when*, and it's
299 /// not worth listing all those and their fancy template signatures as
300 /// friends. But it's not for public consumption.
302 void setCallback_(F&& func);
304 /// A Future's callback is executed when all three of these conditions have
305 /// become true: it has a value (set by the Promise), it has a callback (set
306 /// by then), and it is active (active by default).
308 /// Inactive Futures will activate upon destruction.
309 Future<T>& activate() & {
313 Future<T>& deactivate() & {
317 Future<T> activate() && {
319 return std::move(*this);
321 Future<T> deactivate() && {
323 return std::move(*this);
326 return core_->isActive();
330 void raise(E&& exception) {
331 raise(std::make_exception_ptr(std::forward<E>(exception)));
334 /// Raise an interrupt. If the promise holder has an interrupt
335 /// handler it will be called and potentially stop asynchronous work from
336 /// being done. This is advisory only - a promise holder may not set an
337 /// interrupt handler, or may do anything including ignore. But, if you know
338 /// your future supports this the most likely result is stopping or
339 /// preventing the asynchronous operation (if in time), and the promise
340 /// holder setting an exception on the future. (That may happen
341 /// asynchronously, of course.)
342 void raise(std::exception_ptr interrupt);
345 raise(FutureCancellation());
349 typedef detail::Core<T>* corePtr;
351 // shared core state object
355 Future(corePtr obj) : core_(obj) {}
359 void throwIfInvalid() const;
361 friend class Promise<T>;
365 Make a completed Future by moving in a value. e.g.
368 auto f = makeFuture(std::move(foo));
372 auto f = makeFuture<string>("foo");
375 Future<typename std::decay<T>::type> makeFuture(T&& t);
377 /** Make a completed void Future. */
378 Future<void> makeFuture();
380 /** Make a completed Future by executing a function. If the function throws
381 we capture the exception, otherwise we capture the result. */
385 typename std::enable_if<
386 !std::is_reference<F>::value, bool>::type sdf = false)
387 -> Future<decltype(func())>;
392 -> Future<decltype(func())>;
394 /// Make a failed Future from an exception_ptr.
395 /// Because the Future's type cannot be inferred you have to specify it, e.g.
397 /// auto f = makeFuture<string>(std::current_exception());
399 Future<T> makeFuture(std::exception_ptr const& e);
401 /** Make a Future from an exception type E that can be passed to
402 std::make_exception_ptr(). */
403 template <class T, class E>
404 typename std::enable_if<std::is_base_of<std::exception, E>::value,
406 makeFuture(E const& e);
408 /** Make a Future out of a Try */
410 Future<T> makeFuture(Try<T>&& t);
413 * Return a new Future that will call back on the given Executor.
414 * This is just syntactic sugar for makeFuture().via(executor)
416 * @param executor the Executor to call back on
418 * @returns a void Future that will call back on the given executor
420 template <typename Executor>
421 Future<void> via(Executor* executor);
423 /** When all the input Futures complete, the returned Future will complete.
424 Errors do not cause early termination; this Future will always succeed
425 after all its Futures have finished (whether successfully or with an
428 The Futures are moved in, so your copies are invalid. If you need to
429 chain further from these Futures, use the variant with an output iterator.
431 XXX is this still true?
432 This function is thread-safe for Futures running on different threads.
434 The return type for Future<T> input is a Future<std::vector<Try<T>>>
436 template <class InputIterator>
437 Future<std::vector<Try<
438 typename std::iterator_traits<InputIterator>::value_type::value_type>>>
439 whenAll(InputIterator first, InputIterator last);
441 /// This version takes a varying number of Futures instead of an iterator.
442 /// The return type for (Future<T1>, Future<T2>, ...) input
443 /// is a Future<std::tuple<Try<T1>, Try<T2>, ...>>.
444 /// The Futures are moved in, so your copies are invalid.
445 template <typename... Fs>
446 typename detail::VariadicContext<
447 typename std::decay<Fs>::type::value_type...>::type
450 /** The result is a pair of the index of the first Future to complete and
451 the Try. If multiple Futures complete at the same time (or are already
452 complete when passed in), the "winner" is chosen non-deterministically.
454 This function is thread-safe for Futures running on different threads.
456 template <class InputIterator>
459 Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
460 whenAny(InputIterator first, InputIterator last);
462 /** when n Futures have completed, the Future completes with a vector of
463 the index and Try of those n Futures (the indices refer to the original
464 order, but the result vector will be in an arbitrary order)
468 template <class InputIterator>
469 Future<std::vector<std::pair<
471 Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>>
472 whenN(InputIterator first, InputIterator last, size_t n);
474 /** Wait for the given future to complete on a semaphore. Returns a completed
475 * future containing the result.
477 * NB if the promise for the future would be fulfilled in the same thread that
478 * you call this, it will deadlock.
481 Future<T> waitWithSemaphore(Future<T>&& f);
483 /** Wait for up to `timeout` for the given future to complete. Returns a future
484 * which may or may not be completed depending whether the given future
487 * Note: each call to this starts a (short-lived) thread and allocates memory.
489 template <typename T, class Duration>
490 Future<T> waitWithSemaphore(Future<T>&& f, Duration timeout);
494 #include <folly/wangle/Future-inl.h>