1//
2// detail/wrapped_handler.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2015 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 ASIO_DETAIL_WRAPPED_HANDLER_HPP
12#define ASIO_DETAIL_WRAPPED_HANDLER_HPP
13
14
15#include "asio/detail/bind_handler.hpp"
16#include "asio/detail/handler_alloc_helpers.hpp"
17#include "asio/detail/handler_cont_helpers.hpp"
18#include "asio/detail/handler_invoke_helpers.hpp"
19
20#include "asio/detail/push_options.hpp"
21
22namespace asio {
23namespace detail {
24
25struct is_continuation_delegated
26{
27  template <typename Dispatcher, typename Handler>
28  bool operator()(Dispatcher&, Handler& handler) const
29  {
30    return asio_handler_cont_helpers::is_continuation(handler);
31  }
32};
33
34struct is_continuation_if_running
35{
36  template <typename Dispatcher, typename Handler>
37  bool operator()(Dispatcher& dispatcher, Handler&) const
38  {
39    return dispatcher.running_in_this_thread();
40  }
41};
42
43template <typename Dispatcher, typename Handler,
44    typename IsContinuation = is_continuation_delegated>
45class wrapped_handler
46{
47public:
48  typedef void result_type;
49
50  wrapped_handler(Dispatcher dispatcher, Handler& handler)
51    : dispatcher_(dispatcher),
52      handler_(ASIO_MOVE_CAST(Handler)(handler))
53  {
54  }
55
56  wrapped_handler(const wrapped_handler& other)
57    : dispatcher_(other.dispatcher_),
58      handler_(other.handler_)
59  {
60  }
61
62  wrapped_handler(wrapped_handler&& other)
63    : dispatcher_(other.dispatcher_),
64      handler_(ASIO_MOVE_CAST(Handler)(other.handler_))
65  {
66  }
67
68  void operator()()
69  {
70    dispatcher_.dispatch(ASIO_MOVE_CAST(Handler)(handler_));
71  }
72
73  void operator()() const
74  {
75    dispatcher_.dispatch(handler_);
76  }
77
78  template <typename Arg1>
79  void operator()(const Arg1& arg1)
80  {
81    dispatcher_.dispatch(detail::bind_handler(handler_, arg1));
82  }
83
84  template <typename Arg1>
85  void operator()(const Arg1& arg1) const
86  {
87    dispatcher_.dispatch(detail::bind_handler(handler_, arg1));
88  }
89
90  template <typename Arg1, typename Arg2>
91  void operator()(const Arg1& arg1, const Arg2& arg2)
92  {
93    dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2));
94  }
95
96  template <typename Arg1, typename Arg2>
97  void operator()(const Arg1& arg1, const Arg2& arg2) const
98  {
99    dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2));
100  }
101
102  template <typename Arg1, typename Arg2, typename Arg3>
103  void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3)
104  {
105    dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3));
106  }
107
108  template <typename Arg1, typename Arg2, typename Arg3>
109  void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) const
110  {
111    dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3));
112  }
113
114  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
115  void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3,
116      const Arg4& arg4)
117  {
118    dispatcher_.dispatch(
119        detail::bind_handler(handler_, arg1, arg2, arg3, arg4));
120  }
121
122  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
123  void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3,
124      const Arg4& arg4) const
125  {
126    dispatcher_.dispatch(
127        detail::bind_handler(handler_, arg1, arg2, arg3, arg4));
128  }
129
130  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
131      typename Arg5>
132  void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3,
133      const Arg4& arg4, const Arg5& arg5)
134  {
135    dispatcher_.dispatch(
136        detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5));
137  }
138
139  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
140      typename Arg5>
141  void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3,
142      const Arg4& arg4, const Arg5& arg5) const
143  {
144    dispatcher_.dispatch(
145        detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5));
146  }
147
148//private:
149  Dispatcher dispatcher_;
150  Handler handler_;
151};
152
153template <typename Handler, typename Context>
154class rewrapped_handler
155{
156public:
157  explicit rewrapped_handler(Handler& handler, const Context& context)
158    : context_(context),
159      handler_(ASIO_MOVE_CAST(Handler)(handler))
160  {
161  }
162
163  explicit rewrapped_handler(const Handler& handler, const Context& context)
164    : context_(context),
165      handler_(handler)
166  {
167  }
168
169  rewrapped_handler(const rewrapped_handler& other)
170    : context_(other.context_),
171      handler_(other.handler_)
172  {
173  }
174
175  rewrapped_handler(rewrapped_handler&& other)
176    : context_(ASIO_MOVE_CAST(Context)(other.context_)),
177      handler_(ASIO_MOVE_CAST(Handler)(other.handler_))
178  {
179  }
180
181  void operator()()
182  {
183    handler_();
184  }
185
186  void operator()() const
187  {
188    handler_();
189  }
190
191//private:
192  Context context_;
193  Handler handler_;
194};
195
196template <typename Dispatcher, typename Handler, typename IsContinuation>
197inline void* asio_handler_allocate(std::size_t size,
198    wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)
199{
200  return asio_handler_alloc_helpers::allocate(
201      size, this_handler->handler_);
202}
203
204template <typename Dispatcher, typename Handler, typename IsContinuation>
205inline void asio_handler_deallocate(void* pointer, std::size_t size,
206    wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)
207{
208  asio_handler_alloc_helpers::deallocate(
209      pointer, size, this_handler->handler_);
210}
211
212template <typename Dispatcher, typename Handler, typename IsContinuation>
213inline bool asio_handler_is_continuation(
214    wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)
215{
216  return IsContinuation()(this_handler->dispatcher_, this_handler->handler_);
217}
218
219template <typename Function, typename Dispatcher,
220    typename Handler, typename IsContinuation>
221inline void asio_handler_invoke(Function& function,
222    wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)
223{
224  this_handler->dispatcher_.dispatch(
225      rewrapped_handler<Function, Handler>(
226        function, this_handler->handler_));
227}
228
229template <typename Function, typename Dispatcher,
230    typename Handler, typename IsContinuation>
231inline void asio_handler_invoke(const Function& function,
232    wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)
233{
234  this_handler->dispatcher_.dispatch(
235      rewrapped_handler<Function, Handler>(
236        function, this_handler->handler_));
237}
238
239template <typename Handler, typename Context>
240inline void* asio_handler_allocate(std::size_t size,
241    rewrapped_handler<Handler, Context>* this_handler)
242{
243  return asio_handler_alloc_helpers::allocate(
244      size, this_handler->context_);
245}
246
247template <typename Handler, typename Context>
248inline void asio_handler_deallocate(void* pointer, std::size_t size,
249    rewrapped_handler<Handler, Context>* this_handler)
250{
251  asio_handler_alloc_helpers::deallocate(
252      pointer, size, this_handler->context_);
253}
254
255template <typename Dispatcher, typename Context>
256inline bool asio_handler_is_continuation(
257    rewrapped_handler<Dispatcher, Context>* this_handler)
258{
259  return asio_handler_cont_helpers::is_continuation(
260      this_handler->context_);
261}
262
263template <typename Function, typename Handler, typename Context>
264inline void asio_handler_invoke(Function& function,
265    rewrapped_handler<Handler, Context>* this_handler)
266{
267  asio_handler_invoke_helpers::invoke(
268      function, this_handler->context_);
269}
270
271template <typename Function, typename Handler, typename Context>
272inline void asio_handler_invoke(const Function& function,
273    rewrapped_handler<Handler, Context>* this_handler)
274{
275  asio_handler_invoke_helpers::invoke(
276      function, this_handler->context_);
277}
278
279} // namespace detail
280} // namespace asio
281
282#include "asio/detail/pop_options.hpp"
283
284#endif // ASIO_DETAIL_WRAPPED_HANDLER_HPP
285