(wangle) Use an atomic_flag to make FutureObject threadsafe
[folly.git] / folly / wangle / Future.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #pragma once
18
19 #include <algorithm>
20 #include <exception>
21 #include <functional>
22 #include <memory>
23 #include <type_traits>
24
25 #include "folly/MoveWrapper.h"
26 #include "Promise.h"
27 #include "Try.h"
28
29 namespace folly { namespace wangle {
30
31 template <typename T> struct isFuture;
32
33 template <class T>
34 class Future {
35  public:
36   typedef T value_type;
37
38   // not copyable
39   Future(Future const&) = delete;
40   Future& operator=(Future const&) = delete;
41
42   // movable
43   Future(Future&&);
44   Future& operator=(Future&&);
45
46   ~Future();
47
48   /** Return the reference to result. Should not be called if !isReady().
49     Will rethrow the exception if an exception has been
50     captured.
51
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
55     */
56   typename std::add_lvalue_reference<T>::type
57   value();
58   typename std::add_lvalue_reference<const T>::type
59   value() const;
60
61   /// Returns a future which will call back on the other side of executor.
62   ///
63   ///   f.via(e).then(a); // safe
64   ///
65   ///   f.via(e).then(a).then(b); // faux pas
66   ///
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);
72
73   /// Deprecated alias for via
74   template <typename Executor>
75   Future<T> executeWithSameThread(Executor* executor) {
76     return via(executor);
77   }
78
79   /**
80      Thread-safe version of executeWith
81
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
89
90      Deprecated. Use a Later.
91    */
92   template <typename Executor>
93   void executeWith(Executor* executor, Promise<T>&& cont_promise);
94
95   /** True when the result (or exception) is ready. */
96   bool isReady() const;
97
98   /** A reference to the Try of the value */
99   Try<T>& getTry();
100
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
103     returned. e.g.
104
105     Future<string> f2 = f1.then([](Try<T>&&) { return string("foo"); });
106
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.
110     */
111   /* TODO n3428 and other async frameworks have something like then(scheduler,
112      Future), we probably want to support a similar API (instead of
113      executeWith). */
114   template <class F>
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
118   then(F&& func);
119
120   /// Variant where func returns a Future<T> instead of a T. e.g.
121   ///
122   ///   Future<string> f2 = f1.then(
123   ///     [](Try<T>&&) { return makeFuture<string>("foo"); });
124   template <class F>
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
128   then(F&& func);
129
130   /// Variant where func is an ordinary function (static method, method)
131   ///
132   ///   R doWork(Try<T>&&);
133   ///
134   ///   Future<R> f2 = f1.then(doWork);
135   ///
136   /// or
137   ///
138   ///   struct Worker {
139   ///     static R doWork(Try<T>&&); }
140   ///
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));
147     });
148   }
149
150   /// Variant where func returns a Future<R> instead of a R. e.g.
151   ///
152   ///   struct Worker {
153   ///     Future<R> doWork(Try<T>&&); }
154   ///
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));
161     });
162   }
163
164   /// Variant where func is an member function
165   ///
166   ///   struct Worker {
167   ///     R doWork(Try<T>&&); }
168   ///
169   ///   Worker *w;
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));
176     });
177   }
178
179   /// Variant where func returns a Future<R> instead of a R. e.g.
180   ///
181   ///   struct Worker {
182   ///     Future<R> doWork(Try<T>&&); }
183   ///
184   ///   Worker *w;
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));
191     });
192   }
193
194   /// Convenience method for ignoring the value and creating a Future<void>.
195   /// Exceptions still propagate.
196   Future<void> then();
197
198   /// Use of this method is advanced wizardry.
199   /// XXX should this be protected?
200   template <class F>
201   void setContinuation(F&& func);
202
203  private:
204   typedef detail::FutureObject<T>* objPtr;
205
206   // shared state object
207   objPtr obj_;
208
209   explicit
210   Future(objPtr obj) : obj_(obj) {}
211
212   void throwIfInvalid() const;
213
214   friend class Promise<T>;
215 };
216
217 /**
218   Make a completed Future by moving in a value. e.g.
219
220     string foo = "foo";
221     auto f = makeFuture(std::move(foo));
222
223   or
224
225     auto f = makeFuture<string>("foo");
226 */
227 template <class T>
228 Future<typename std::decay<T>::type> makeFuture(T&& t);
229
230 /** Make a completed void Future. */
231 Future<void> makeFuture();
232
233 /** Make a completed Future by executing a function. If the function throws
234   we capture the exception, otherwise we capture the result. */
235 template <class F>
236 auto makeFutureTry(
237   F&& func,
238   typename std::enable_if<
239     !std::is_reference<F>::value, bool>::type sdf = false)
240   -> Future<decltype(func())>;
241
242 template <class F>
243 auto makeFutureTry(
244   F const& func)
245   -> Future<decltype(func())>;
246
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.
249 ///
250 ///   auto f = makeFuture<string>(std::current_exception());
251 template <class T>
252 Future<T> makeFuture(std::exception_ptr const& e);
253
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);
259
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
263   error).
264
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.
267
268   XXX is this still true?
269   This function is thread-safe for Futures running on different threads.
270
271   The return type for Future<T> input is a Future<std::vector<Try<T>>>
272   */
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);
277
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
285 whenAll(Fs&&... fs);
286
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.
290
291   This function is thread-safe for Futures running on different threads.
292   */
293 template <class InputIterator>
294 Future<std::pair<
295   size_t,
296   Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>
297 whenAny(InputIterator first, InputIterator last);
298
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)
302
303   Not thread safe.
304   */
305 template <class InputIterator>
306 Future<std::vector<std::pair<
307   size_t,
308   Try<typename std::iterator_traits<InputIterator>::value_type::value_type>>>>
309 whenN(InputIterator first, InputIterator last, size_t n);
310
311 }} // folly::wangle
312
313 #include "Future-inl.h"