Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / asio / impl / compose.hpp
1 //
2 // impl/compose.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 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/detail/handler_alloc_helpers.hpp>
20 #include <boost/asio/detail/handler_cont_helpers.hpp>
21 #include <boost/asio/detail/handler_invoke_helpers.hpp>
22 #include <boost/asio/detail/type_traits.hpp>
23 #include <boost/asio/detail/variadic_templates.hpp>
24 #include <boost/asio/executor_work_guard.hpp>
25 #include <boost/asio/is_executor.hpp>
26 #include <boost/asio/system_executor.hpp>
27
28 #include <boost/asio/detail/push_options.hpp>
29
30 namespace boost {
31 namespace asio {
32
33 namespace detail
34 {
35   template <typename>
36   struct composed_io_executors;
37
38   template <>
39   struct composed_io_executors<void()>
40   {
41     composed_io_executors() BOOST_ASIO_NOEXCEPT
42       : head_(system_executor())
43     {
44     }
45
46     typedef system_executor head_type;
47     system_executor head_;
48   };
49
50   inline composed_io_executors<void()> make_composed_io_executors()
51   {
52     return composed_io_executors<void()>();
53   }
54
55   template <typename Head>
56   struct composed_io_executors<void(Head)>
57   {
58     explicit composed_io_executors(const Head& ex) BOOST_ASIO_NOEXCEPT
59       : head_(ex)
60     {
61     }
62
63     typedef Head head_type;
64     Head head_;
65   };
66
67   template <typename Head>
68   inline composed_io_executors<void(Head)>
69   make_composed_io_executors(const Head& head)
70   {
71     return composed_io_executors<void(Head)>(head);
72   }
73
74 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
75
76   template <typename Head, typename... Tail>
77   struct composed_io_executors<void(Head, Tail...)>
78   {
79     explicit composed_io_executors(const Head& head,
80         const Tail&... tail) BOOST_ASIO_NOEXCEPT
81       : head_(head),
82         tail_(tail...)
83     {
84     }
85
86     void reset()
87     {
88       head_.reset();
89       tail_.reset();
90     }
91
92     typedef Head head_type;
93     Head head_;
94     composed_io_executors<void(Tail...)> tail_;
95   };
96
97   template <typename Head, typename... Tail>
98   inline composed_io_executors<void(Head, Tail...)>
99   make_composed_io_executors(const Head& head, const Tail&... tail)
100   {
101     return composed_io_executors<void(Head, Tail...)>(head, tail...);
102   }
103
104 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
105
106 #define BOOST_ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF(n) \
107   template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
108   struct composed_io_executors<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
109   { \
110     explicit composed_io_executors(const Head& head, \
111         BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) BOOST_ASIO_NOEXCEPT \
112       : head_(head), \
113         tail_(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) \
114     { \
115     } \
116   \
117     void reset() \
118     { \
119       head_.reset(); \
120       tail_.reset(); \
121     } \
122   \
123     typedef Head head_type; \
124     Head head_; \
125     composed_io_executors<void(BOOST_ASIO_VARIADIC_TARGS(n))> tail_; \
126   }; \
127   \
128   template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
129   inline composed_io_executors<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
130   make_composed_io_executors(const Head& head, \
131       BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) \
132   { \
133     return composed_io_executors< \
134       void(Head, BOOST_ASIO_VARIADIC_TARGS(n))>( \
135         head, BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)); \
136   } \
137   /**/
138   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF)
139 #undef BOOST_ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF
140
141 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
142
143   template <typename>
144   struct composed_work;
145
146   template <>
147   struct composed_work<void()>
148   {
149     typedef composed_io_executors<void()> executors_type;
150
151     composed_work(const executors_type&) BOOST_ASIO_NOEXCEPT
152       : head_(system_executor())
153     {
154     }
155
156     void reset()
157     {
158       head_.reset();
159     }
160
161     typedef system_executor head_type;
162     executor_work_guard<system_executor> head_;
163   };
164
165   template <typename Head>
166   struct composed_work<void(Head)>
167   {
168     typedef composed_io_executors<void(Head)> executors_type;
169
170     explicit composed_work(const executors_type& ex) BOOST_ASIO_NOEXCEPT
171       : head_(ex.head_)
172     {
173     }
174
175     void reset()
176     {
177       head_.reset();
178     }
179
180     typedef Head head_type;
181     executor_work_guard<Head> head_;
182   };
183
184 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
185
186   template <typename Head, typename... Tail>
187   struct composed_work<void(Head, Tail...)>
188   {
189     typedef composed_io_executors<void(Head, Tail...)> executors_type;
190
191     explicit composed_work(const executors_type& ex) BOOST_ASIO_NOEXCEPT
192       : head_(ex.head_),
193         tail_(ex.tail_)
194     {
195     }
196
197     void reset()
198     {
199       head_.reset();
200       tail_.reset();
201     }
202
203     typedef Head head_type;
204     executor_work_guard<Head> head_;
205     composed_work<void(Tail...)> tail_;
206   };
207
208 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
209
210 #define BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \
211   template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
212   struct composed_work<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
213   { \
214     typedef composed_io_executors<void(Head, \
215       BOOST_ASIO_VARIADIC_TARGS(n))> executors_type; \
216   \
217     explicit composed_work(const executors_type& ex) BOOST_ASIO_NOEXCEPT \
218       : head_(ex.head_), \
219         tail_(ex.tail_) \
220     { \
221     } \
222   \
223     void reset() \
224     { \
225       head_.reset(); \
226       tail_.reset(); \
227     } \
228   \
229     typedef Head head_type; \
230     executor_work_guard<Head> head_; \
231     composed_work<void(BOOST_ASIO_VARIADIC_TARGS(n))> tail_; \
232   }; \
233   /**/
234   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF)
235 #undef BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF
236
237 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
238
239 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
240   template <typename Impl, typename Work, typename Handler, typename Signature>
241   class composed_op;
242
243   template <typename Impl, typename Work, typename Handler,
244       typename R, typename... Args>
245   class composed_op<Impl, Work, Handler, R(Args...)>
246 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
247   template <typename Impl, typename Work, typename Handler, typename Signature>
248   class composed_op
249 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
250   {
251   public:
252     composed_op(BOOST_ASIO_MOVE_ARG(Impl) impl,
253         BOOST_ASIO_MOVE_ARG(Work) work,
254         BOOST_ASIO_MOVE_ARG(Handler) handler)
255       : impl_(BOOST_ASIO_MOVE_CAST(Impl)(impl)),
256         work_(BOOST_ASIO_MOVE_CAST(Work)(work)),
257         handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
258         invocations_(0)
259     {
260     }
261
262 #if defined(BOOST_ASIO_HAS_MOVE)
263     composed_op(composed_op&& other)
264       : impl_(BOOST_ASIO_MOVE_CAST(Impl)(other.impl_)),
265         work_(BOOST_ASIO_MOVE_CAST(Work)(other.work_)),
266         handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
267         invocations_(other.invocations_)
268     {
269     }
270 #endif // defined(BOOST_ASIO_HAS_MOVE)
271
272     typedef typename associated_executor<Handler,
273         typename Work::head_type>::type executor_type;
274
275     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
276     {
277       return (get_associated_executor)(handler_, work_.head_.get_executor());
278     }
279
280     typedef typename associated_allocator<Handler,
281       std::allocator<void> >::type allocator_type;
282
283     allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
284     {
285       return (get_associated_allocator)(handler_, std::allocator<void>());
286     }
287
288 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
289
290     template<typename... T>
291     void operator()(BOOST_ASIO_MOVE_ARG(T)... t)
292     {
293       if (invocations_ < ~unsigned(0))
294         ++invocations_;
295       impl_(*this, BOOST_ASIO_MOVE_CAST(T)(t)...);
296     }
297
298     void complete(Args... args)
299     {
300       this->work_.reset();
301       this->handler_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
302     }
303
304 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
305
306     void operator()()
307     {
308       if (invocations_ < ~unsigned(0))
309         ++invocations_;
310       impl_(*this);
311     }
312
313     void complete()
314     {
315       this->work_.reset();
316       this->handler_();
317     }
318
319 #define BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF(n) \
320     template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
321     void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
322     { \
323       if (invocations_ < ~unsigned(0)) \
324         ++invocations_; \
325       impl_(*this, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
326     } \
327     \
328     template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
329     void complete(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
330     { \
331       this->work_.reset(); \
332       this->handler_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
333     } \
334     /**/
335     BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF)
336 #undef BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF
337
338 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
339
340   //private:
341     Impl impl_;
342     Work work_;
343     Handler handler_;
344     unsigned invocations_;
345   };
346
347   template <typename Impl, typename Work, typename Handler, typename Signature>
348   inline void* asio_handler_allocate(std::size_t size,
349       composed_op<Impl, Work, Handler, Signature>* this_handler)
350   {
351     return boost_asio_handler_alloc_helpers::allocate(
352         size, this_handler->handler_);
353   }
354
355   template <typename Impl, typename Work, typename Handler, typename Signature>
356   inline void asio_handler_deallocate(void* pointer, std::size_t size,
357       composed_op<Impl, Work, Handler, Signature>* this_handler)
358   {
359     boost_asio_handler_alloc_helpers::deallocate(
360         pointer, size, this_handler->handler_);
361   }
362
363   template <typename Impl, typename Work, typename Handler, typename Signature>
364   inline bool asio_handler_is_continuation(
365       composed_op<Impl, Work, Handler, Signature>* this_handler)
366   {
367     return this_handler->invocations_ > 1 ? true
368       : boost_asio_handler_cont_helpers::is_continuation(
369           this_handler->handler_);
370   }
371
372   template <typename Function, typename Impl,
373       typename Work, typename Handler, typename Signature>
374   inline void asio_handler_invoke(Function& function,
375       composed_op<Impl, Work, Handler, Signature>* this_handler)
376   {
377     boost_asio_handler_invoke_helpers::invoke(
378         function, this_handler->handler_);
379   }
380
381   template <typename Function, typename Impl,
382       typename Work, typename Handler, typename Signature>
383   inline void asio_handler_invoke(const Function& function,
384       composed_op<Impl, Work, Handler, Signature>* this_handler)
385   {
386     boost_asio_handler_invoke_helpers::invoke(
387         function, this_handler->handler_);
388   }
389
390   template <typename Signature, typename Executors>
391   class initiate_composed_op
392   {
393   public:
394     typedef typename composed_io_executors<Executors>::head_type executor_type;
395
396     template <typename T>
397     explicit initiate_composed_op(BOOST_ASIO_MOVE_ARG(T) executors)
398       : executors_(BOOST_ASIO_MOVE_CAST(T)(executors))
399     {
400     }
401
402     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
403     {
404       return executors_.head_;
405     }
406
407     template <typename Handler, typename Impl>
408     void operator()(BOOST_ASIO_MOVE_ARG(Handler) handler,
409         BOOST_ASIO_MOVE_ARG(Impl) impl) const
410     {
411       composed_op<typename decay<Impl>::type, composed_work<Executors>,
412         typename decay<Handler>::type, Signature>(
413           BOOST_ASIO_MOVE_CAST(Impl)(impl),
414           composed_work<Executors>(executors_),
415           BOOST_ASIO_MOVE_CAST(Handler)(handler))();
416     }
417
418   private:
419     composed_io_executors<Executors> executors_;
420   };
421
422   template <typename Signature, typename Executors>
423   inline initiate_composed_op<Signature, Executors> make_initiate_composed_op(
424       BOOST_ASIO_MOVE_ARG(composed_io_executors<Executors>) executors)
425   {
426     return initiate_composed_op<Signature, Executors>(
427         BOOST_ASIO_MOVE_CAST(composed_io_executors<Executors>)(executors));
428   }
429
430   template <typename IoObject>
431   inline typename IoObject::executor_type
432   get_composed_io_executor(IoObject& io_object)
433   {
434     return io_object.get_executor();
435   }
436
437   template <typename Executor>
438   inline const Executor& get_composed_io_executor(const Executor& ex,
439       typename enable_if<is_executor<Executor>::value>::type* = 0)
440   {
441     return ex;
442   }
443 } // namespace detail
444
445 #if !defined(GENERATING_DOCUMENTATION)
446 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
447
448 template <typename CompletionToken, typename Signature,
449     typename Implementation, typename... IoObjectsOrExecutors>
450 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)
451 async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
452     BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
453     BOOST_ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors)
454 {
455   return async_initiate<CompletionToken, Signature>(
456       detail::make_initiate_composed_op<Signature>(
457         detail::make_composed_io_executors(
458           detail::get_composed_io_executor(
459             BOOST_ASIO_MOVE_CAST(IoObjectsOrExecutors)(
460               io_objects_or_executors))...)),
461       token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation));
462 }
463
464 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
465
466 template <typename CompletionToken, typename Signature, typename Implementation>
467 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)
468 async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
469     BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
470 {
471   return async_initiate<CompletionToken, Signature>(
472       detail::make_initiate_composed_op<Signature>(
473         detail::make_composed_io_executors()),
474       token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation));
475 }
476
477 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \
478   BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n
479
480 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \
481   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1))
482 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \
483   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
484   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2))
485 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \
486   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
487   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
488   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3))
489 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \
490   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
491   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
492   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
493   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4))
494 # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \
495   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
496   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
497   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
498   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
499   detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5))
500
501 #define BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \
502   template <typename CompletionToken, typename Signature, \
503       typename Implementation, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
504   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) \
505   async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, \
506       BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
507       BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
508   { \
509     return async_initiate<CompletionToken, Signature>( \
510         detail::make_initiate_composed_op<Signature>( \
511           detail::make_composed_io_executors( \
512             BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))), \
513         token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation)); \
514   } \
515   /**/
516   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF)
517 #undef BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF
518
519 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR
520 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1
521 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2
522 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3
523 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4
524 #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5
525
526 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
527 #endif // !defined(GENERATING_DOCUMENTATION)
528
529 } // namespace asio
530 } // namespace boost
531
532 #include <boost/asio/detail/pop_options.hpp>
533
534 #endif // BOOST_ASIO_IMPL_COMPOSE_HPP