Codemod: use #include angle brackets in folly and thrift
[folly.git] / folly / wangle / Later.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 <folly/wangle/Executor.h>
20 #include <folly/wangle/Future.h>
21 #include <folly/Optional.h>
22
23 namespace folly { namespace wangle {
24
25 template <typename T> struct isLaterOrFuture;
26 template <typename T> struct isLater;
27
28 /*
29  * Since wangle primitives (promise/future) are not thread safe, it is difficult
30  * to build complex asynchronous workflows. A Later allows you to build such a
31  * workflow before actually launching it so that callbacks can be set in a
32  * threadsafe manner.
33  *
34  * The interface to add additional work is the same as future: a then() method
35  * that takes a function that can return either a type T, a Future<T>, or a
36  * Later<T>
37  *
38  * Thread transitions are done by using executors and calling the via() method.
39  *
40  * Here is an example of a workflow:
41  *
42  * Later<ClientRequest> later(std::move(request));
43  *
44  * auto future = later.
45  *   .via(cpuExecutor)
46  *   .then([=](Try<ClientRequest>&& t) { return doCpuWork(t.value()); })
47  *   .via(diskExecutor)
48  *   .then([=](Try<CpuResponse>&& t) { return doDiskWork(t.value()); })
49  *   .via(serverExecutor)
50  *   .then([=]Try<DiskResponse>&& t) { return sendClientResponse(t.value()); })
51  *   .launch();
52  *
53  * Although this workflow traverses many threads, we are able to string
54  * continuations together in a threadsafe manner.
55  *
56  * Laters can also be used to wrap preexisting asynchronous modules that were
57  * not built with wangle in mind. You can create a Later with a function that
58  * takes a callback as input. The function will not actually be called until
59  * launch(), allowing you to string then() statements on top of the callback.
60  */
61 template <class T>
62 class Later {
63  public:
64   typedef T value_type;
65
66   /*
67    * This default constructor is used to build an asynchronous workflow that
68    * takes no input.
69    */
70   template <class U = void,
71             class = typename std::enable_if<std::is_void<U>::value>::type,
72             class = typename std::enable_if<std::is_same<T, U>::value>::type>
73   Later();
74
75   /*
76    * Lift a Future into a Later
77    */
78   /* implicit */ Later(Future<T>&& f);
79
80   /*
81    * This constructor is used to build an asynchronous workflow that takes a
82    * value as input, and that value is passed in.
83    */
84   template <class U,
85             class = typename std::enable_if<!std::is_void<U>::value>::type,
86             class = typename std::enable_if<std::is_same<T, U>::value>::type>
87   explicit Later(U&& input);
88
89   /*
90    * This constructor is used to wrap a pre-existing cob-style asynchronous api
91    * so that it can be used in wangle in a threadsafe manner. wangle provides
92    * the callback to this pre-existing api, and this callback will fulfill a
93    * promise so as to incorporate this api into the workflow.
94    *
95    * Example usage:
96    *
97    * // This adds two ints asynchronously. cob is called in another thread.
98    * void addAsync(int a, int b, std::function<void(int&&)>&& cob);
99    *
100    * Later<int> asyncWrapper([=](std::function<void(int&&)>&& fn) {
101    *   addAsync(1, 2, std::move(fn));
102    * });
103    */
104   template <class U,
105             class = typename std::enable_if<!std::is_void<U>::value>::type,
106             class = typename std::enable_if<std::is_same<T, U>::value>::type>
107   explicit Later(std::function<void(std::function<void(U&&)>&&)>&& fn);
108
109   /*
110    * then() adds additional work to the end of the workflow. If the lambda
111    * provided to then() returns a future, that future must be fulfilled in the
112    * same thread of the last set executor (either at constructor or from a call
113    * to via()).
114    */
115   template <class F>
116   typename std::enable_if<
117     !isLaterOrFuture<typename std::result_of<F(Try<T>&&)>::type>::value,
118     Later<typename std::result_of<F(Try<T>&&)>::type> >::type
119   then(F&& fn);
120
121   template <class F>
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   then(F&& fn);
126
127   /*
128    * If the function passed to then() returns a Later<T>, calls to then() will
129    * be chained to the new Later before launching the new Later.
130    *
131    * This can be used to build asynchronous modules that can be called from a
132    * user thread and completed in a callback thread. Callbacks can be set up
133    * ahead of time without thread safety issues.
134    *
135    * Using the Later(std::function<void(std::function<void(T&&)>)>&& fn)
136    * constructor, you can wrap existing asynchronous modules with a Later and
137    * can chain it to wangle asynchronous workflows via this call.
138    */
139   template <class F>
140   typename std::enable_if<
141     isLater<typename std::result_of<F(Try<T>&&)>::type>::value,
142     Later<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
143   then(F&& fn);
144
145   /*
146    * Resets the executor - all then() calls made after the call to via() will be
147    * made in the new executor. The Executor must outlive.
148    */
149   Later<T> via(Executor* executor);
150
151   /*
152    * Starts the workflow. The function provided in the constructor will be
153    * called in the executor provided in the constructor. Subsequent then()
154    * calls will be made, potentially changing threads if a via() call is made.
155    * The future returned will be fulfilled in the last executor.
156    *
157    * Thread safety issues of Futures still apply. If you want to wait on the
158    * Future, it must be done in the thread that will fulfil it.
159    */
160   Future<T> launch();
161
162   /*
163    * Same as launch, only no Future is returned. This guarantees thread safe
164    * cleanup of the internal Futures, even if the Later completes in a different
165    * thread than the thread that calls fireAndForget().
166    *
167    * Deprecated. Use launch()
168    */
169   void fireAndForget() { launch(); }
170
171  private:
172   Promise<void> starter_;
173   folly::Optional<Future<T>> future_;
174
175   struct hide { };
176
177   explicit Later(Promise<void>&& starter);
178
179   template <class U>
180   friend class Later;
181 };
182
183 }}
184
185 #include "Later-inl.h"