1 //
2 // async_ops.hpp
3 // ~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #ifndef ARCHETYPES_ASYNC_OPS_HPP
12 #define ARCHETYPES_ASYNC_OPS_HPP
13 
14 #include <boost/asio/associated_allocator.hpp>
15 #include <boost/asio/associated_executor.hpp>
16 #include <boost/asio/async_result.hpp>
17 #include <boost/asio/error.hpp>
18 
19 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
20 # include <boost/bind.hpp>
21 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
22 # include <functional>
23 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
24 
25 namespace archetypes {
26 
27 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
28 namespace bindns = boost;
29 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
30 namespace bindns = std;
31 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
32 
33 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void ())34 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void())
35 async_op_0(BOOST_ASIO_MOVE_ARG(CompletionToken) token)
36 {
37   typedef typename boost::asio::async_completion<CompletionToken,
38     void()>::completion_handler_type handler_type;
39 
40   boost::asio::async_completion<CompletionToken,
41     void()> completion(token);
42 
43   typename boost::asio::associated_allocator<handler_type>::type a
44     = boost::asio::get_associated_allocator(completion.completion_handler);
45 
46   typename boost::asio::associated_executor<handler_type>::type ex
47     = boost::asio::get_associated_executor(completion.completion_handler);
48 
49   ex.post(BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler), a);
50 
51   return completion.result.get();
52 }
53 
54 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void (boost::system::error_code))55 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(boost::system::error_code))
56 async_op_ec_0(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
57 {
58   typedef typename boost::asio::async_completion<CompletionToken,
59     void(boost::system::error_code)>::completion_handler_type handler_type;
60 
61   boost::asio::async_completion<CompletionToken,
62     void(boost::system::error_code)> completion(token);
63 
64   typename boost::asio::associated_allocator<handler_type>::type a
65     = boost::asio::get_associated_allocator(completion.completion_handler);
66 
67   typename boost::asio::associated_executor<handler_type>::type ex
68     = boost::asio::get_associated_executor(completion.completion_handler);
69 
70   if (ok)
71   {
72     ex.post(
73         bindns::bind(
74           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
75           boost::system::error_code()), a);
76   }
77   else
78   {
79     ex.post(
80         bindns::bind(
81           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
82           boost::system::error_code(boost::asio::error::operation_aborted)), a);
83   }
84 
85   return completion.result.get();
86 }
87 
88 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void (std::exception_ptr))89 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(std::exception_ptr))
90 async_op_ex_0(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
91 {
92   typedef typename boost::asio::async_completion<CompletionToken,
93     void(std::exception_ptr)>::completion_handler_type handler_type;
94 
95   boost::asio::async_completion<CompletionToken,
96     void(std::exception_ptr)> completion(token);
97 
98   typename boost::asio::associated_allocator<handler_type>::type a
99     = boost::asio::get_associated_allocator(completion.completion_handler);
100 
101   typename boost::asio::associated_executor<handler_type>::type ex
102     = boost::asio::get_associated_executor(completion.completion_handler);
103 
104   if (ok)
105   {
106     ex.post(
107         bindns::bind(
108           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
109           std::exception_ptr()), a);
110   }
111   else
112   {
113     ex.post(
114         bindns::bind(
115           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
116           std::make_exception_ptr(std::runtime_error("blah"))), a);
117   }
118 
119   return completion.result.get();
120 }
121 
122 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void (int))123 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int))
124 async_op_1(BOOST_ASIO_MOVE_ARG(CompletionToken) token)
125 {
126   typedef typename boost::asio::async_completion<CompletionToken,
127     void(int)>::completion_handler_type handler_type;
128 
129   boost::asio::async_completion<CompletionToken,
130     void(int)> completion(token);
131 
132   typename boost::asio::associated_allocator<handler_type>::type a
133     = boost::asio::get_associated_allocator(completion.completion_handler);
134 
135   typename boost::asio::associated_executor<handler_type>::type ex
136     = boost::asio::get_associated_executor(completion.completion_handler);
137 
138   ex.post(
139       bindns::bind(
140         BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
141         42), a);
142 
143   return completion.result.get();
144 }
145 
146 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void (boost::system::error_code,int))147 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
148     void(boost::system::error_code, int))
149 async_op_ec_1(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
150 {
151   typedef typename boost::asio::async_completion<CompletionToken,
152     void(boost::system::error_code, int)>::completion_handler_type
153       handler_type;
154 
155   boost::asio::async_completion<CompletionToken,
156     void(boost::system::error_code, int)> completion(token);
157 
158   typename boost::asio::associated_allocator<handler_type>::type a
159     = boost::asio::get_associated_allocator(completion.completion_handler);
160 
161   typename boost::asio::associated_executor<handler_type>::type ex
162     = boost::asio::get_associated_executor(completion.completion_handler);
163 
164   if (ok)
165   {
166     ex.post(
167         bindns::bind(
168           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
169           boost::system::error_code(), 42), a);
170   }
171   else
172   {
173     ex.post(
174         bindns::bind(
175           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
176           boost::system::error_code(boost::asio::error::operation_aborted),
177           0), a);
178   }
179 
180   return completion.result.get();
181 }
182 
183 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void (std::exception_ptr,int))184 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(std::exception_ptr, int))
185 async_op_ex_1(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
186 {
187   typedef typename boost::asio::async_completion<CompletionToken,
188     void(std::exception_ptr, int)>::completion_handler_type
189       handler_type;
190 
191   boost::asio::async_completion<CompletionToken,
192     void(std::exception_ptr, int)> completion(token);
193 
194   typename boost::asio::associated_allocator<handler_type>::type a
195     = boost::asio::get_associated_allocator(completion.completion_handler);
196 
197   typename boost::asio::associated_executor<handler_type>::type ex
198     = boost::asio::get_associated_executor(completion.completion_handler);
199 
200   if (ok)
201   {
202     ex.post(
203         bindns::bind(
204           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
205           std::exception_ptr(), 42), a);
206   }
207   else
208   {
209     ex.post(
210         bindns::bind(
211           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
212           std::make_exception_ptr(std::runtime_error("blah")), 0), a);
213   }
214 
215   return completion.result.get();
216 }
217 
218 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void (int,double))219 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int, double))
220 async_op_2(BOOST_ASIO_MOVE_ARG(CompletionToken) token)
221 {
222   typedef typename boost::asio::async_completion<CompletionToken,
223     void(int, double)>::completion_handler_type handler_type;
224 
225   boost::asio::async_completion<CompletionToken,
226     void(int, double)> completion(token);
227 
228   typename boost::asio::associated_allocator<handler_type>::type a
229     = boost::asio::get_associated_allocator(completion.completion_handler);
230 
231   typename boost::asio::associated_executor<handler_type>::type ex
232     = boost::asio::get_associated_executor(completion.completion_handler);
233 
234   ex.post(
235       bindns::bind(
236         BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
237         42, 2.0), a);
238 
239   return completion.result.get();
240 }
241 
242 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void (boost::system::error_code,int,double))243 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
244     void(boost::system::error_code, int, double))
245 async_op_ec_2(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
246 {
247   typedef typename boost::asio::async_completion<CompletionToken,
248     void(boost::system::error_code, int, double)>::completion_handler_type
249       handler_type;
250 
251   boost::asio::async_completion<CompletionToken,
252     void(boost::system::error_code, int, double)> completion(token);
253 
254   typename boost::asio::associated_allocator<handler_type>::type a
255     = boost::asio::get_associated_allocator(completion.completion_handler);
256 
257   typename boost::asio::associated_executor<handler_type>::type ex
258     = boost::asio::get_associated_executor(completion.completion_handler);
259 
260   if (ok)
261   {
262     ex.post(
263         bindns::bind(
264           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
265           boost::system::error_code(), 42, 2.0), a);
266   }
267   else
268   {
269     ex.post(
270         bindns::bind(
271           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
272           boost::system::error_code(boost::asio::error::operation_aborted),
273           0, 0.0), a);
274   }
275 
276   return completion.result.get();
277 }
278 
279 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void (std::exception_ptr,int,double))280 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
281     void(std::exception_ptr, int, double))
282 async_op_ex_2(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
283 {
284   typedef typename boost::asio::async_completion<CompletionToken,
285     void(std::exception_ptr, int, double)>::completion_handler_type
286       handler_type;
287 
288   boost::asio::async_completion<CompletionToken,
289     void(std::exception_ptr, int, double)> completion(token);
290 
291   typename boost::asio::associated_allocator<handler_type>::type a
292     = boost::asio::get_associated_allocator(completion.completion_handler);
293 
294   typename boost::asio::associated_executor<handler_type>::type ex
295     = boost::asio::get_associated_executor(completion.completion_handler);
296 
297   if (ok)
298   {
299     ex.post(
300         bindns::bind(
301           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
302           std::exception_ptr(), 42, 2.0), a);
303   }
304   else
305   {
306     ex.post(
307         bindns::bind(
308           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
309           std::make_exception_ptr(std::runtime_error("blah")), 0, 0.0), a);
310   }
311 
312   return completion.result.get();
313 }
314 
315 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void (int,double,char))316 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int, double, char))
317 async_op_3(BOOST_ASIO_MOVE_ARG(CompletionToken) token)
318 {
319   typedef typename boost::asio::async_completion<CompletionToken,
320     void(int, double, char)>::completion_handler_type handler_type;
321 
322   boost::asio::async_completion<CompletionToken,
323     void(int, double, char)> completion(token);
324 
325   typename boost::asio::associated_allocator<handler_type>::type a
326     = boost::asio::get_associated_allocator(completion.completion_handler);
327 
328   typename boost::asio::associated_executor<handler_type>::type ex
329     = boost::asio::get_associated_executor(completion.completion_handler);
330 
331   ex.post(
332       bindns::bind(
333         BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
334         42, 2.0, 'a'), a);
335 
336   return completion.result.get();
337 }
338 
339 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void (boost::system::error_code,int,double,char))340 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
341     void(boost::system::error_code, int, double, char))
342 async_op_ec_3(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
343 {
344   typedef typename boost::asio::async_completion<CompletionToken,
345     void(boost::system::error_code, int, double, char)>::completion_handler_type
346       handler_type;
347 
348   boost::asio::async_completion<CompletionToken,
349     void(boost::system::error_code, int, double, char)> completion(token);
350 
351   typename boost::asio::associated_allocator<handler_type>::type a
352     = boost::asio::get_associated_allocator(completion.completion_handler);
353 
354   typename boost::asio::associated_executor<handler_type>::type ex
355     = boost::asio::get_associated_executor(completion.completion_handler);
356 
357   if (ok)
358   {
359     ex.post(
360         bindns::bind(
361           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
362           boost::system::error_code(), 42, 2.0, 'a'), a);
363   }
364   else
365   {
366     ex.post(
367         bindns::bind(
368           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
369           boost::system::error_code(boost::asio::error::operation_aborted),
370           0, 0.0, 'z'), a);
371   }
372 
373   return completion.result.get();
374 }
375 
376 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void (std::exception_ptr,int,double,char))377 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,
378     void(std::exception_ptr, int, double, char))
379 async_op_ex_3(bool ok, BOOST_ASIO_MOVE_ARG(CompletionToken) token)
380 {
381   typedef typename boost::asio::async_completion<CompletionToken,
382     void(std::exception_ptr, int, double, char)>::completion_handler_type
383       handler_type;
384 
385   boost::asio::async_completion<CompletionToken,
386     void(std::exception_ptr, int, double, char)> completion(token);
387 
388   typename boost::asio::associated_allocator<handler_type>::type a
389     = boost::asio::get_associated_allocator(completion.completion_handler);
390 
391   typename boost::asio::associated_executor<handler_type>::type ex
392     = boost::asio::get_associated_executor(completion.completion_handler);
393 
394   if (ok)
395   {
396     ex.post(
397         bindns::bind(
398           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
399           std::exception_ptr(), 42, 2.0, 'a'), a);
400   }
401   else
402   {
403     ex.post(
404         bindns::bind(
405           BOOST_ASIO_MOVE_CAST(handler_type)(completion.completion_handler),
406           std::make_exception_ptr(std::runtime_error("blah")),
407           0, 0.0, 'z'), a);
408   }
409 
410   return completion.result.get();
411 }
412 
413 } // namespace archetypes
414 
415 #endif // ARCHETYPES_ASYNC_OPS_HPP
416