1 //
2 // impl/compose.hpp
3 // ~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 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 BOOST_ASIO_IMPL_COMPOSE_HPP
12 #define BOOST_ASIO_IMPL_COMPOSE_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include <boost/asio/detail/config.hpp>
19 #include <boost/asio/associated_executor.hpp>
20 #include <boost/asio/detail/handler_alloc_helpers.hpp>
21 #include <boost/asio/detail/handler_cont_helpers.hpp>
22 #include <boost/asio/detail/handler_invoke_helpers.hpp>
23 #include <boost/asio/detail/type_traits.hpp>
24 #include <boost/asio/detail/variadic_templates.hpp>
25 #include <boost/asio/execution/executor.hpp>
26 #include <boost/asio/execution/outstanding_work.hpp>
27 #include <boost/asio/executor_work_guard.hpp>
28 #include <boost/asio/is_executor.hpp>
29 #include <boost/asio/system_executor.hpp>
30 
31 #include <boost/asio/detail/push_options.hpp>
32 
33 namespace boost {
34 namespace asio {
35 
36 namespace detail
37 {
38   template <typename Executor, typename = void>
39   class composed_work_guard
40   {
41   public:
42     typedef typename decay<
43         typename prefer_result<Executor,
44           execution::outstanding_work_t::tracked_t
45         >::type
46       >::type executor_type;
47 
composed_work_guard(const Executor & ex)48     composed_work_guard(const Executor& ex)
49       : executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
50     {
51     }
52 
reset()53     void reset()
54     {
55     }
56 
get_executor() const57     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
58     {
59       return executor_;
60     }
61 
62   private:
63     executor_type executor_;
64   };
65 
66 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
67 
68   template <typename Executor>
69   struct composed_work_guard<Executor,
70       typename enable_if<
71         !execution::is_executor<Executor>::value
72       >::type> : executor_work_guard<Executor>
73   {
composed_work_guardboost::asio::detail::composed_work_guard74     composed_work_guard(const Executor& ex)
75       : executor_work_guard<Executor>(ex)
76     {
77     }
78   };
79 
80 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
81 
82   template <typename>
83   struct composed_io_executors;
84 
85   template <>
86   struct composed_io_executors<void()>
87   {
composed_io_executorsboost::asio::detail::composed_io_executors88     composed_io_executors() BOOST_ASIO_NOEXCEPT
89       : head_(system_executor())
90     {
91     }
92 
93     typedef system_executor head_type;
94     system_executor head_;
95   };
96 
make_composed_io_executors()97   inline composed_io_executors<void()> make_composed_io_executors()
98   {
99     return composed_io_executors<void()>();
100   }
101 
102   template <typename Head>
103   struct composed_io_executors<void(Head)>
104   {
composed_io_executorsboost::asio::detail::composed_io_executors105     explicit composed_io_executors(const Head& ex) BOOST_ASIO_NOEXCEPT
106       : head_(ex)
107     {
108     }
109 
110     typedef Head head_type;
111     Head head_;
112   };
113 
114   template <typename Head>
115   inline composed_io_executors<void(Head)>
make_composed_io_executors(const Head & head)116   make_composed_io_executors(const Head& head)
117   {
118     return composed_io_executors<void(Head)>(head);
119   }
120 
121 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
122 
123   template <typename Head, typename... Tail>
124   struct composed_io_executors<void(Head, Tail...)>
125   {
composed_io_executorsboost::asio::detail::composed_io_executors126     explicit composed_io_executors(const Head& head,
127         const Tail&... tail) BOOST_ASIO_NOEXCEPT
128       : head_(head),
129         tail_(tail...)
130     {
131     }
132 
resetboost::asio::detail::composed_io_executors133     void reset()
134     {
135       head_.reset();
136       tail_.reset();
137     }
138 
139     typedef Head head_type;
140     Head head_;
141     composed_io_executors<void(Tail...)> tail_;
142   };
143 
144   template <typename Head, typename... Tail>
145   inline composed_io_executors<void(Head, Tail...)>
make_composed_io_executors(const Head & head,const Tail &...tail)146   make_composed_io_executors(const Head& head, const Tail&... tail)
147   {
148     return composed_io_executors<void(Head, Tail...)>(head, tail...);
149   }
150 
151 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
152 
153 #define BOOST_ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF(n) \
154   template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
155   struct composed_io_executors<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
156   { \
157     explicit composed_io_executors(const Head& head, \
158         BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) BOOST_ASIO_NOEXCEPT \
159       : head_(head), \
160         tail_(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) \
161     { \
162     } \
163   \
164     void reset() \
165     { \
166       head_.reset(); \
167       tail_.reset(); \
168     } \
169   \
170     typedef Head head_type; \
171     Head head_; \
172     composed_io_executors<void(BOOST_ASIO_VARIADIC_TARGS(n))> tail_; \
173   }; \
174   \
175   template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
176   inline composed_io_executors<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
177   make_composed_io_executors(const Head& head, \
178       BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) \
179   { \
180     return composed_io_executors< \
181       void(Head, BOOST_ASIO_VARIADIC_TARGS(n))>( \
182         head, BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)); \
183   } \
184   /**/
185   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF)
186 #undef BOOST_ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF
187 
188 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
189 
190   template <typename>
191   struct composed_work;
192 
193   template <>
194   struct composed_work<void()>
195   {
196     typedef composed_io_executors<void()> executors_type;
197 
composed_workboost::asio::detail::composed_work198     composed_work(const executors_type&) BOOST_ASIO_NOEXCEPT
199       : head_(system_executor())
200     {
201     }
202 
resetboost::asio::detail::composed_work203     void reset()
204     {
205       head_.reset();
206     }
207 
208     typedef system_executor head_type;
209     composed_work_guard<system_executor> head_;
210   };
211 
212   template <typename Head>
213   struct composed_work<void(Head)>
214   {
215     typedef composed_io_executors<void(Head)> executors_type;
216 
composed_workboost::asio::detail::composed_work217     explicit composed_work(const executors_type& ex) BOOST_ASIO_NOEXCEPT
218       : head_(ex.head_)
219     {
220     }
221 
resetboost::asio::detail::composed_work222     void reset()
223     {
224       head_.reset();
225     }
226 
227     typedef Head head_type;
228     composed_work_guard<Head> head_;
229   };
230 
231 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
232 
233   template <typename Head, typename... Tail>
234   struct composed_work<void(Head, Tail...)>
235   {
236     typedef composed_io_executors<void(Head, Tail...)> executors_type;
237 
composed_workboost::asio::detail::composed_work238     explicit composed_work(const executors_type& ex) BOOST_ASIO_NOEXCEPT
239       : head_(ex.head_),
240         tail_(ex.tail_)
241     {
242     }
243 
resetboost::asio::detail::composed_work244     void reset()
245     {
246       head_.reset();
247       tail_.reset();
248     }
249 
250     typedef Head head_type;
251     composed_work_guard<Head> head_;
252     composed_work<void(Tail...)> tail_;
253   };
254 
255 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
256 
257 #define BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \
258   template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
259   struct composed_work<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
260   { \
261     typedef composed_io_executors<void(Head, \
262       BOOST_ASIO_VARIADIC_TARGS(n))> executors_type; \
263   \
264     explicit composed_work(const executors_type& ex) BOOST_ASIO_NOEXCEPT \
265       : head_(ex.head_), \
266         tail_(ex.tail_) \
267     { \
268     } \
269   \
270     void reset() \
271     { \
272       head_.reset(); \
273       tail_.reset(); \
274     } \
275   \
276     typedef Head head_type; \
277     composed_work_guard<Head> head_; \
278     composed_work<void(BOOST_ASIO_VARIADIC_TARGS(n))> tail_; \
279   }; \
280   /**/
281   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF)
282 #undef BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF
283 
284 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
285 
286 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
287   template <typename Impl, typename Work, typename Handler, typename Signature>
288   class composed_op;
289 
290   template <typename Impl, typename Work, typename Handler,
291       typename R, typename... Args>
292   class composed_op<Impl, Work, Handler, R(Args...)>
293 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
294   template <typename Impl, typename Work, typename Handler, typename Signature>
295   class composed_op
296 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
297   {
298   public:
299     template <typename I, typename W, typename H>
composed_op(BOOST_ASIO_MOVE_ARG (I)impl,BOOST_ASIO_MOVE_ARG (W)work,BOOST_ASIO_MOVE_ARG (H)handler)300     composed_op(BOOST_ASIO_MOVE_ARG(I) impl,
301         BOOST_ASIO_MOVE_ARG(W) work,
302         BOOST_ASIO_MOVE_ARG(H) handler)
303       : impl_(BOOST_ASIO_MOVE_CAST(I)(impl)),
304         work_(BOOST_ASIO_MOVE_CAST(W)(work)),
305         handler_(BOOST_ASIO_MOVE_CAST(H)(handler)),
306         invocations_(0)
307     {
308     }
309 
310 #if defined(BOOST_ASIO_HAS_MOVE)
composed_op(composed_op && other)311     composed_op(composed_op&& other)
312       : impl_(BOOST_ASIO_MOVE_CAST(Impl)(other.impl_)),
313         work_(BOOST_ASIO_MOVE_CAST(Work)(other.work_)),
314         handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
315         invocations_(other.invocations_)
316     {
317     }
318 #endif // defined(BOOST_ASIO_HAS_MOVE)
319 
320     typedef typename associated_executor<Handler,
321         typename composed_work_guard<
322           typename Work::head_type
323         >::executor_type
324       >::type executor_type;
325 
get_executor() const326     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
327     {
328       return (get_associated_executor)(handler_, work_.head_.get_executor());
329     }
330 
331     typedef typename associated_allocator<Handler,
332       std::allocator<void> >::type allocator_type;
333 
get_allocator() const334     allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
335     {
336       return (get_associated_allocator)(handler_, std::allocator<void>());
337     }
338 
339 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
340 
341     template<typename... T>
operator ()(BOOST_ASIO_MOVE_ARG (T)...t)342     void operator()(BOOST_ASIO_MOVE_ARG(T)... t)
343     {
344       if (invocations_ < ~0u)
345         ++invocations_;
346       impl_(*this, BOOST_ASIO_MOVE_CAST(T)(t)...);
347     }
348 
complete(Args...args)349     void complete(Args... args)
350     {
351       this->work_.reset();
352       this->handler_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
353     }
354 
355 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
356 
operator ()()357     void operator()()
358     {
359       if (invocations_ < ~0u)
360         ++invocations_;
361       impl_(*this);
362     }
363 
complete()364     void complete()
365     {
366       this->work_.reset();
367       this->handler_();
368     }
369 
370 #define BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF(n) \
371     template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
372     void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
373     { \
374       if (invocations_ < ~0u) \
375         ++invocations_; \
376       impl_(*this, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
377     } \
378     \
379     template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
380     void complete(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
381     { \
382       this->work_.reset(); \
383       this->handler_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
384     } \
385     /**/
386     BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF)
387 #undef BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF
388 
389 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
390 
391   //private:
392     Impl impl_;
393     Work work_;
394     Handler handler_;
395     unsigned invocations_;
396   };
397 
398   template <typename Impl, typename Work, typename Handler, typename Signature>
399   inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,composed_op<Impl,Work,Handler,Signature> * this_handler)400   asio_handler_allocate(std::size_t size,
401       composed_op<Impl, Work, Handler, Signature>* this_handler)
402   {
403 #if defined(BOOST_ASIO_NO_DEPRECATED)
404     boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
405     return asio_handler_allocate_is_no_longer_used();
406 #else // defined(BOOST_ASIO_NO_DEPRECATED)
407     return boost_asio_handler_alloc_helpers::allocate(
408         size, this_handler->handler_);
409 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
410   }
411 
412   template <typename Impl, typename Work, typename Handler, typename Signature>
413   inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,composed_op<Impl,Work,Handler,Signature> * this_handler)414   asio_handler_deallocate(void* pointer, std::size_t size,
415       composed_op<Impl, Work, Handler, Signature>* this_handler)
416   {
417     boost_asio_handler_alloc_helpers::deallocate(
418         pointer, size, this_handler->handler_);
419 #if defined(BOOST_ASIO_NO_DEPRECATED)
420     return asio_handler_deallocate_is_no_longer_used();
421 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
422   }
423 
424   template <typename Impl, typename Work, typename Handler, typename Signature>
asio_handler_is_continuation(composed_op<Impl,Work,Handler,Signature> * this_handler)425   inline bool asio_handler_is_continuation(
426       composed_op<Impl, Work, Handler, Signature>* this_handler)
427   {
428     return this_handler->invocations_ > 1 ? true
429       : boost_asio_handler_cont_helpers::is_continuation(
430           this_handler->handler_);
431   }
432 
433   template <typename Function, typename Impl,
434       typename Work, typename Handler, typename Signature>
435   inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,composed_op<Impl,Work,Handler,Signature> * this_handler)436   asio_handler_invoke(Function& function,
437       composed_op<Impl, Work, Handler, Signature>* this_handler)
438   {
439     boost_asio_handler_invoke_helpers::invoke(
440         function, this_handler->handler_);
441 #if defined(BOOST_ASIO_NO_DEPRECATED)
442     return asio_handler_invoke_is_no_longer_used();
443 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
444   }
445 
446   template <typename Function, typename Impl,
447       typename Work, typename Handler, typename Signature>
448   inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,composed_op<Impl,Work,Handler,Signature> * this_handler)449   asio_handler_invoke(const Function& function,
450       composed_op<Impl, Work, Handler, Signature>* this_handler)
451   {
452     boost_asio_handler_invoke_helpers::invoke(
453         function, this_handler->handler_);
454 #if defined(BOOST_ASIO_NO_DEPRECATED)
455     return asio_handler_invoke_is_no_longer_used();
456 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
457   }
458 
459   template <typename Signature, typename Executors>
460   class initiate_composed_op
461   {
462   public:
463     typedef typename composed_io_executors<Executors>::head_type executor_type;
464 
465     template <typename T>
initiate_composed_op(int,BOOST_ASIO_MOVE_ARG (T)executors)466     explicit initiate_composed_op(int, BOOST_ASIO_MOVE_ARG(T) executors)
467       : executors_(BOOST_ASIO_MOVE_CAST(T)(executors))
468     {
469     }
470 
get_executor() const471     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
472     {
473       return executors_.head_;
474     }
475 
476     template <typename Handler, typename Impl>
operator ()(BOOST_ASIO_MOVE_ARG (Handler)handler,BOOST_ASIO_MOVE_ARG (Impl)impl) const477     void operator()(BOOST_ASIO_MOVE_ARG(Handler) handler,
478         BOOST_ASIO_MOVE_ARG(Impl) impl) const
479     {
480       composed_op<typename decay<Impl>::type, composed_work<Executors>,
481         typename decay<Handler>::type, Signature>(
482           BOOST_ASIO_MOVE_CAST(Impl)(impl),
483           composed_work<Executors>(executors_),
484           BOOST_ASIO_MOVE_CAST(Handler)(handler))();
485     }
486 
487   private:
488     composed_io_executors<Executors> executors_;
489   };
490 
491   template <typename Signature, typename Executors>
make_initiate_composed_op(BOOST_ASIO_MOVE_ARG (composed_io_executors<Executors>)executors)492   inline initiate_composed_op<Signature, Executors> make_initiate_composed_op(
493       BOOST_ASIO_MOVE_ARG(composed_io_executors<Executors>) executors)
494   {
495     return initiate_composed_op<Signature, Executors>(0,
496         BOOST_ASIO_MOVE_CAST(composed_io_executors<Executors>)(executors));
497   }
498 
499   template <typename IoObject>
500   inline typename IoObject::executor_type
get_composed_io_executor(IoObject & io_object,typename enable_if<!is_executor<IoObject>::value>::type * =0,typename enable_if<!execution::is_executor<IoObject>::value>::type * =0)501   get_composed_io_executor(IoObject& io_object,
502       typename enable_if<
503         !is_executor<IoObject>::value
504       >::type* = 0,
505       typename enable_if<
506         !execution::is_executor<IoObject>::value
507       >::type* = 0)
508   {
509     return io_object.get_executor();
510   }
511 
512   template <typename Executor>
get_composed_io_executor(const Executor & ex,typename enable_if<is_executor<Executor>::value||execution::is_executor<Executor>::value>::type * =0)513   inline const Executor& get_composed_io_executor(const Executor& ex,
514       typename enable_if<
515         is_executor<Executor>::value
516           || execution::is_executor<Executor>::value
517       >::type* = 0)
518   {
519     return ex;
520   }
521 } // namespace detail
522 
523 #if !defined(GENERATING_DOCUMENTATION)
524 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
525 
526 template <typename CompletionToken, typename Signature,
527     typename Implementation, typename... IoObjectsOrExecutors>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,Signature)528 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)
529 async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
530     BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
531     BOOST_ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors)
532 {
533   return async_initiate<CompletionToken, Signature>(
534       detail::make_initiate_composed_op<Signature>(
535         detail::make_composed_io_executors(
536           detail::get_composed_io_executor(
537             BOOST_ASIO_MOVE_CAST(IoObjectsOrExecutors)(
538               io_objects_or_executors))...)),
539       token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation));
540 }
541 
542 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
543 
544 template <typename CompletionToken, typename Signature, typename Implementation>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,Signature)545 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)
546 async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
547     BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
548 {
549   return async_initiate<CompletionToken, Signature>(
550       detail::make_initiate_composed_op<Signature>(
551         detail::make_composed_io_executors()),
552       token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation));
553 }
554 
555 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \
556   BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n
557 
558 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \
559   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1))
560 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \
561   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
562   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2))
563 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \
564   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
565   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
566   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3))
567 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \
568   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
569   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
570   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
571   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4))
572 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \
573   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
574   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
575   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
576   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
577   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5))
578 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6 \
579   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
580   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
581   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
582   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
583   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5)), \
584   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T6)(x6))
585 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7 \
586   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
587   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
588   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
589   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
590   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5)), \
591   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T6)(x6)), \
592   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T7)(x7))
593 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8 \
594   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
595   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
596   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
597   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
598   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5)), \
599   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T6)(x6)), \
600   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T7)(x7)), \
601   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T8)(x8))
602 
603 #define BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \
604   template <typename CompletionToken, typename Signature, \
605       typename Implementation, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
606   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) \
607   async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, \
608       BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
609       BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
610   { \
611     return async_initiate<CompletionToken, Signature>( \
612         detail::make_initiate_composed_op<Signature>( \
613           detail::make_composed_io_executors( \
614             BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))), \
615         token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation)); \
616   } \
617   /**/
618   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF)
619 #undef BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF
620 
621 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR
622 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1
623 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2
624 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3
625 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4
626 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5
627 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6
628 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7
629 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8
630 
631 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
632 #endif // !defined(GENERATING_DOCUMENTATION)
633 
634 } // namespace asio
635 } // namespace boost
636 
637 #include <boost/asio/detail/pop_options.hpp>
638 
639 #endif // BOOST_ASIO_IMPL_COMPOSE_HPP
640