Apache Mesos
async.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License
12 
13 #ifndef __ASYNC_HPP__
14 #define __ASYNC_HPP__
15 
16 #include <type_traits>
17 
18 #include <process/dispatch.hpp>
19 #include <process/future.hpp>
20 #include <process/id.hpp>
21 #include <process/pid.hpp>
22 #include <process/process.hpp>
23 
24 #include <stout/lambda.hpp>
25 #include <stout/nothing.hpp>
26 #include <stout/preprocessor.hpp>
27 #include <stout/result_of.hpp>
28 
29 namespace process {
30 
31 // Provides an abstraction for asynchronously executing a function
32 // (note the declarations are here and definitions below since
33 // defining and declaring below will require defining the default
34 // argument when declaring these as friends in AsyncExecutor which is
35 // brittle).
36 
37 template <typename F>
39  const F& f,
40  typename std::enable_if<!std::is_void<typename result_of<F()>::type>::value>::type* = nullptr); // NOLINT(whitespace/line_length)
41 
42 
43 template <typename F>
44 Future<Nothing> async(
45  const F& f,
46  typename std::enable_if<std::is_void<typename result_of<F()>::type>::value>::type* = nullptr); // NOLINT(whitespace/line_length)
47 
48 
49 #define TEMPLATE(Z, N, DATA) \
50  template <typename F, ENUM_PARAMS(N, typename A)> \
51  Future<typename result_of<F(ENUM_PARAMS(N, A))>::type> async( \
52  const F& f, \
53  ENUM_BINARY_PARAMS(N, A, a), \
54  typename std::enable_if<!std::is_void<typename result_of<F(ENUM_PARAMS(N, A))>::type>::value>::type* = nullptr); /* NOLINT(whitespace/line_length) */ \
55  \
56  \
57  template <typename F, ENUM_PARAMS(N, typename A)> \
58  Future<Nothing> async( \
59  const F& f, \
60  ENUM_BINARY_PARAMS(N, A, a), \
61  typename std::enable_if<std::is_void<typename result_of<F(ENUM_PARAMS(N, A))>::type>::value>::type* = nullptr); // NOLINT(whitespace/line_length)
62 
63  REPEAT_FROM_TO(1, 13, TEMPLATE, _) // Args A0 -> A11.
64 #undef TEMPLATE
65 
66 
67 // TODO(vinod): Merge this into ExecutorProcess.
68 class AsyncExecutorProcess : public Process<AsyncExecutorProcess>
69 {
70 private:
71  friend class AsyncExecutor;
72 
73  AsyncExecutorProcess() : ProcessBase(ID::generate("__async_executor__")) {}
74  ~AsyncExecutorProcess() override {}
75 
76  // Not copyable, not assignable.
77  AsyncExecutorProcess(const AsyncExecutorProcess&);
78  AsyncExecutorProcess& operator=(const AsyncExecutorProcess&);
79 
80  template <
81  typename F,
82  typename std::enable_if<
84  typename result_of<F()>::type execute(const F& f)
85  {
86  terminate(self()); // Terminate process after function returns.
87  return f();
88  }
89 
90  template <
91  typename F,
92  typename std::enable_if<
93  std::is_void<typename result_of<F()>::type>::value, int>::type = 0>
94  Nothing execute(const F& f)
95  {
96  terminate(self()); // Terminate process after function returns.
97  f();
98  return Nothing();
99  }
100 
101 #define TEMPLATE(Z, N, DATA) \
102  template < \
103  typename F, \
104  ENUM_PARAMS(N, typename A), \
105  typename std::enable_if< \
106  !std::is_void< \
107  typename result_of<F(ENUM_PARAMS(N, A))>::type>::value, \
108  int>::type = 0> \
109  typename result_of<F(ENUM_PARAMS(N, A))>::type execute( \
110  const F& f, ENUM_BINARY_PARAMS(N, A, a)) \
111  { \
112  terminate(self()); /* Terminate process after function returns. */ \
113  return f(ENUM_PARAMS(N, a)); \
114  } \
115  \
116  template < \
117  typename F, \
118  ENUM_PARAMS(N, typename A), \
119  typename std::enable_if< \
120  std::is_void< \
121  typename result_of<F(ENUM_PARAMS(N, A))>::type>::value, \
122  int>::type = 0> \
123  Nothing execute( \
124  const F& f, ENUM_BINARY_PARAMS(N, A, a)) \
125  { \
126  terminate(self()); /* Terminate process after function returns. */ \
127  f(ENUM_PARAMS(N, a)); \
128  return Nothing(); \
129  }
130 
131  REPEAT_FROM_TO(1, 13, TEMPLATE, _) // Args A0 -> A11.
132 #undef TEMPLATE
133 };
134 
135 
136 // This is a wrapper around AsyncExecutorProcess.
138 {
139 private:
140  // Declare async functions as friends.
141  template <typename F>
143  const F& f,
144  typename std::enable_if<!std::is_void<typename result_of<F()>::type>::value>::type*); // NOLINT(whitespace/line_length)
145 
146  template <typename F>
147  friend Future<Nothing> async(
148  const F& f,
149  typename std::enable_if<std::is_void<typename result_of<F()>::type>::value>::type*); // NOLINT(whitespace/line_length)
150 
151 #define TEMPLATE(Z, N, DATA) \
152  template <typename F, ENUM_PARAMS(N, typename A)> \
153  friend Future<typename result_of<F(ENUM_PARAMS(N, A))>::type> async( \
154  const F& f, \
155  ENUM_BINARY_PARAMS(N, A, a), \
156  typename std::enable_if<!std::is_void<typename result_of<F(ENUM_PARAMS(N, A))>::type>::value>::type*); /* NOLINT(whitespace/line_length) */ \
157  \
158  template <typename F, ENUM_PARAMS(N, typename A)> \
159  friend Future<Nothing> async( \
160  const F& f, \
161  ENUM_BINARY_PARAMS(N, A, a), \
162  typename std::enable_if<std::is_void<typename result_of<F(ENUM_PARAMS(N, A))>::type>::value>::type*); // NOLINT(whitespace/line_length)
163 
164  REPEAT_FROM_TO(1, 13, TEMPLATE, _) // Args A0 -> A11.
165 #undef TEMPLATE
166 
167  AsyncExecutor()
168  {
169  process = spawn(new AsyncExecutorProcess(), true); // Automatically GC.
170  }
171 
172  virtual ~AsyncExecutor() {}
173 
174  // Not copyable, not assignable.
176  AsyncExecutor& operator=(const AsyncExecutor&);
177 
178  template <typename F>
180  const F& f,
181  typename std::enable_if<!std::is_void<typename result_of<F()>::type>::value>::type* = nullptr) // NOLINT(whitespace/line_length)
182  {
183  // Need to disambiguate overloaded method.
184  typename result_of<F()>::type(AsyncExecutorProcess::*method)(const F&) =
185  &AsyncExecutorProcess::execute<F>;
186 
187  return dispatch(process, method, f);
188  }
189 
190  template <typename F>
192  const F& f,
193  typename std::enable_if<std::is_void<typename result_of<F()>::type>::value>::type* = nullptr) // NOLINT(whitespace/line_length)
194  {
195  // Need to disambiguate overloaded method.
196  Nothing(AsyncExecutorProcess::*method)(const F&) =
197  &AsyncExecutorProcess::execute<F>;
198 
199  return dispatch(process, method, f);
200  }
201 
202 #define TEMPLATE(Z, N, DATA) \
203  template <typename F, ENUM_PARAMS(N, typename A)> \
204  Future<typename result_of<F(ENUM_PARAMS(N, A))>::type> execute( \
205  const F& f, \
206  ENUM_BINARY_PARAMS(N, A, a), \
207  typename std::enable_if<!std::is_void<typename result_of<F(ENUM_PARAMS(N, A))>::type>::value>::type* = nullptr) /* NOLINT(whitespace/line_length) */ \
208  { \
209  /* Need to disambiguate overloaded method. */ \
210  typename result_of<F(ENUM_PARAMS(N, A))>::type(AsyncExecutorProcess::*method)(const F&, ENUM_PARAMS(N, A)) = /* NOLINT(whitespace/line_length) */ \
211  &AsyncExecutorProcess::execute<F, ENUM_PARAMS(N, A)>; \
212  \
213  return dispatch(process, method, f, ENUM_PARAMS(N, a)); \
214  } \
215  \
216  template <typename F, ENUM_PARAMS(N, typename A)> \
217  Future<Nothing> execute( \
218  const F& f, \
219  ENUM_BINARY_PARAMS(N, A, a), \
220  typename std::enable_if<std::is_void<typename result_of<F(ENUM_PARAMS(N, A))>::type>::value>::type* = nullptr) /* NOLINT(whitespace/line_length) */ \
221  { \
222  /* Need to disambiguate overloaded method. */ \
223  Nothing(AsyncExecutorProcess::*method)(const F&, ENUM_PARAMS(N, A)) = \
224  &AsyncExecutorProcess::execute<F, ENUM_PARAMS(N, A)>; \
225  \
226  return dispatch(process, method, f, ENUM_PARAMS(N, a)); \
227  }
228 
229  REPEAT_FROM_TO(1, 13, TEMPLATE, _) // Args A0 -> A11.
230 #undef TEMPLATE
231 
233 };
234 
235 
236 // Provides an abstraction for asynchronously executing a function.
237 template <typename F>
239  const F& f,
240  typename std::enable_if<!std::is_void<typename result_of<F()>::type>::value>::type*) // NOLINT(whitespace/line_length)
241 {
242  return AsyncExecutor().execute(f);
243 }
244 
245 
246 template <typename F>
248  const F& f,
249  typename std::enable_if<std::is_void<typename result_of<F()>::type>::value>::type*) // NOLINT(whitespace/line_length)
250 {
251  return AsyncExecutor().execute(f);
252 }
253 
254 
255 #define TEMPLATE(Z, N, DATA) \
256  template <typename F, ENUM_PARAMS(N, typename A)> \
257  Future<typename result_of<F(ENUM_PARAMS(N, A))>::type> async( \
258  const F& f, \
259  ENUM_BINARY_PARAMS(N, A, a), \
260  typename std::enable_if<!std::is_void<typename result_of<F(ENUM_PARAMS(N, A))>::type>::value>::type*) /* NOLINT(whitespace/line_length) */ \
261  { \
262  return AsyncExecutor().execute(f, ENUM_PARAMS(N, a)); \
263  } \
264  \
265  template <typename F, ENUM_PARAMS(N, typename A)> \
266  Future<Nothing> async( \
267  const F& f, \
268  ENUM_BINARY_PARAMS(N, A, a), \
269  typename std::enable_if<std::is_void<typename result_of<F(ENUM_PARAMS(N, A))>::type>::value>::type*) /* NOLINT(whitespace/line_length) */ \
270  { \
271  return AsyncExecutor().execute(f, ENUM_PARAMS(N, a)); \
272  }
273 
274  REPEAT_FROM_TO(1, 13, TEMPLATE, _) // Args A0 -> A11.
275 #undef TEMPLATE
276 
277 } // namespace process {
278 
279 #endif // __ASYNC_HPP__
std::string generate(const std::string &prefix="")
Returns &#39;prefix(N)&#39; where N represents the number of instances where the same prefix (wrt...
Definition: nothing.hpp:16
void execute(const std::string &script)
F && f
Definition: defer.hpp:270
REPEAT_FROM_TO(1, 13, TEMPLATE, _) class AsyncExecutorProcess
Definition: async.hpp:63
Definition: process.hpp:72
UPID spawn(ProcessBase *process, bool manage=false)
Spawn a new process.
void terminate(const UPID &pid, bool inject=true)
Sends a TerminateEvent to the given process.
Definition: async.hpp:137
void dispatch(const PID< T > &pid, void(T::*method)())
Definition: dispatch.hpp:174
Future< typename result_of< F()>::type > async(const F &f, typename std::enable_if<!std::is_void< typename result_of< F()>::type >::value >::type *=nullptr)
Definition: async.hpp:238
Result< Process > process(pid_t pid)
Definition: freebsd.hpp:30
A "process identifier" used to uniquely identify a process when dispatching messages.
Definition: pid.hpp:289
#define TEMPLATE(Z, N, DATA)
Definition: async.hpp:255
Definition: executor.hpp:48
Try< uint32_t > type(const std::string &path)
Definition: process.hpp:505
Definition: future.hpp:58