1//
2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// Official repository: https://github.com/boostorg/beast
8//
9
10#ifndef BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
11#define BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
12
13#include <boost/beast/core/error.hpp>
14#include <boost/beast/core/detail/tuple.hpp>
15#include <boost/asio/associator.hpp>
16#include <boost/asio/handler_continuation_hook.hpp>
17#include <boost/core/ignore_unused.hpp>
18#include <boost/mp11/integer_sequence.hpp>
19#include <boost/bind/std_placeholders.hpp>
20#include <boost/is_placeholder.hpp>
21#include <functional>
22#include <type_traits>
23#include <utility>
24
25namespace boost {
26namespace beast {
27namespace detail {
28
29//------------------------------------------------------------------------------
30//
31// bind_handler
32//
33//------------------------------------------------------------------------------
34
35template<class Handler, class... Args>
36class bind_wrapper
37{
38 using args_type = detail::tuple<Args...>;
39
40 Handler h_;
41 args_type args_;
42
43 template <template <typename, typename> class Associator,
44 typename T, typename DefaultCandidate>
45 friend struct net::associator;
46
47 template<class Arg, class Vals>
48 static
49 typename std::enable_if<
50 std::is_placeholder<typename
51 std::decay<Arg>::type>::value == 0 &&
52 boost::is_placeholder<typename
53 std::decay<Arg>::type>::value == 0,
54 Arg&&>::type
55 extract(Arg&& arg, Vals&& vals)
56 {
57 boost::ignore_unused(vals);
58 return std::forward<Arg>(arg);
59 }
60
61 template<class Arg, class Vals>
62 static
63 typename std::enable_if<
64 std::is_placeholder<typename
65 std::decay<Arg>::type>::value != 0,
66 tuple_element<std::is_placeholder<
67 typename std::decay<Arg>::type>::value - 1,
68 Vals>>::type&&
69 extract(Arg&&, Vals&& vals)
70 {
71 return detail::get<std::is_placeholder<
72 typename std::decay<Arg>::type>::value - 1>(
73 std::forward<Vals>(vals));
74 }
75
76 template<class Arg, class Vals>
77 static
78 typename std::enable_if<
79 boost::is_placeholder<typename
80 std::decay<Arg>::type>::value != 0 &&
81 std::is_placeholder<typename
82 std::decay<Arg>::type>::value == 0,
83 tuple_element<boost::is_placeholder<
84 typename std::decay<Arg>::type>::value - 1,
85 Vals>>::type&&
86 extract(Arg&&, Vals&& vals)
87 {
88 return detail::get<boost::is_placeholder<
89 typename std::decay<Arg>::type>::value - 1>(
90 std::forward<Vals>(vals));
91 }
92
93 template<class ArgsTuple, std::size_t... S>
94 static
95 void
96 invoke(
97 Handler& h,
98 ArgsTuple& args,
99 tuple<>&&,
100 mp11::index_sequence<S...>)
101 {
102 boost::ignore_unused(args);
103 h(detail::get<S>(std::move(args))...);
104 }
105
106 template<
107 class ArgsTuple,
108 class ValsTuple,
109 std::size_t... S>
110 static
111 void
112 invoke(
113 Handler& h,
114 ArgsTuple& args,
115 ValsTuple&& vals,
116 mp11::index_sequence<S...>)
117 {
118 boost::ignore_unused(args);
119 boost::ignore_unused(vals);
120 h(extract(detail::get<S>(std::move(args)),
121 std::forward<ValsTuple>(vals))...);
122 }
123
124public:
125 using result_type = void; // asio needs this
126
127 bind_wrapper(bind_wrapper&&) = default;
128 bind_wrapper(bind_wrapper const&) = default;
129
130 template<
131 class DeducedHandler,
132 class... Args_>
133 explicit
134 bind_wrapper(
135 DeducedHandler&& handler,
136 Args_&&... args)
137 : h_(std::forward<DeducedHandler>(handler))
138 , args_(std::forward<Args_>(args)...)
139 {
140 }
141
142 template<class... Values>
143 void
144 operator()(Values&&... values)
145 {
146 invoke(h_, args_,
147 tuple<Values&&...>(
148 std::forward<Values>(values)...),
149 mp11::index_sequence_for<Args...>());
150 }
151
152 //
153
154 friend
155 bool asio_handler_is_continuation(
156 bind_wrapper* op)
157 {
158 using boost::asio::asio_handler_is_continuation;
159 return asio_handler_is_continuation(
160 std::addressof(op->h_));
161 }
162};
163
164template<class Handler, class... Args>
165class bind_back_wrapper;
166
167template<class Handler, class... Args>
168class bind_front_wrapper;
169
170//------------------------------------------------------------------------------
171//
172// bind_front
173//
174//------------------------------------------------------------------------------
175
176template<class Handler, class... Args>
177class bind_front_wrapper
178{
179 Handler h_;
180 detail::tuple<Args...> args_;
181
182 template <template <typename, typename> class Associator,
183 typename T, typename DefaultCandidate>
184 friend struct net::associator;
185
186 template<std::size_t... I, class... Ts>
187 void
188 invoke(
189 std::false_type,
190 mp11::index_sequence<I...>,
191 Ts&&... ts)
192 {
193 h_( detail::get<I>(std::move(args_))...,
194 std::forward<Ts>(ts)...);
195 }
196
197 template<std::size_t... I, class... Ts>
198 void
199 invoke(
200 std::true_type,
201 mp11::index_sequence<I...>,
202 Ts&&... ts)
203 {
204 std::mem_fn(h_)(
205 detail::get<I>(std::move(args_))...,
206 std::forward<Ts>(ts)...);
207 }
208
209public:
210 using result_type = void; // asio needs this
211
212 bind_front_wrapper(bind_front_wrapper&&) = default;
213 bind_front_wrapper(bind_front_wrapper const&) = default;
214
215 template<class Handler_, class... Args_>
216 bind_front_wrapper(
217 Handler_&& handler,
218 Args_&&... args)
219 : h_(std::forward<Handler_>(handler))
220 , args_(std::forward<Args_>(args)...)
221 {
222 }
223
224 template<class... Ts>
225 void operator()(Ts&&... ts)
226 {
227 invoke(
228 std::is_member_function_pointer<Handler>{},
229 mp11::index_sequence_for<Args...>{},
230 std::forward<Ts>(ts)...);
231 }
232
233 //
234
235 friend
236 bool asio_handler_is_continuation(
237 bind_front_wrapper* op)
238 {
239 using boost::asio::asio_handler_is_continuation;
240 return asio_handler_is_continuation(
241 std::addressof(op->h_));
242 }
243};
244
245} // detail
246} // beast
247} // boost
248
249//------------------------------------------------------------------------------
250
251namespace boost {
252namespace asio {
253
254template <template <typename, typename> class Associator,
255 typename Handler, typename... Args, typename DefaultCandidate>
256struct associator<Associator,
257 beast::detail::bind_wrapper<Handler, Args...>, DefaultCandidate>
258 : Associator<Handler, DefaultCandidate>
259{
260 static typename Associator<Handler, DefaultCandidate>::type get(
261 const beast::detail::bind_wrapper<Handler, Args...>& h) noexcept
262 {
263 return Associator<Handler, DefaultCandidate>::get(h.h_);
264 }
265
266 static auto get(const beast::detail::bind_wrapper<Handler, Args...>& h,
267 const DefaultCandidate& c) noexcept
268 -> decltype(Associator<Handler, DefaultCandidate>::get(h.h_, c))
269 {
270 return Associator<Handler, DefaultCandidate>::get(h.h_, c);
271 }
272};
273
274template <template <typename, typename> class Associator,
275 typename Handler, typename... Args, typename DefaultCandidate>
276struct associator<Associator,
277 beast::detail::bind_front_wrapper<Handler, Args...>, DefaultCandidate>
278 : Associator<Handler, DefaultCandidate>
279{
280 static typename Associator<Handler, DefaultCandidate>::type get(
281 const beast::detail::bind_front_wrapper<Handler, Args...>& h) noexcept
282 {
283 return Associator<Handler, DefaultCandidate>::get(h.h_);
284 }
285
286 static auto get(const beast::detail::bind_front_wrapper<Handler, Args...>& h,
287 const DefaultCandidate& c) noexcept
288 -> decltype(Associator<Handler, DefaultCandidate>::get(h.h_, c))
289 {
290 return Associator<Handler, DefaultCandidate>::get(h.h_, c);
291 }
292};
293
294} // asio
295} // boost
296
297//------------------------------------------------------------------------------
298
299namespace std {
300
301// VFALCO Using std::bind on a completion handler will
302// cause undefined behavior later, because the executor
303// associated with the handler is not propagated to the
304// wrapper returned by std::bind; these overloads are
305// deleted to prevent mistakes. If this creates a problem
306// please contact me.
307
308template<class Handler, class... Args>
309void
310bind(boost::beast::detail::bind_wrapper<
311 Handler, Args...>, ...) = delete;
312
313template<class Handler, class... Args>
314void
315bind(boost::beast::detail::bind_front_wrapper<
316 Handler, Args...>, ...) = delete;
317
318} // std
319
320//------------------------------------------------------------------------------
321
322#endif
323

source code of boost/libs/beast/include/boost/beast/core/detail/bind_handler.hpp