]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/beast/core/detail/bind_handler.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / beast / core / detail / bind_handler.hpp
CommitLineData
b32b8144 1//
92f5a8d4 2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
b32b8144
FG
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
92f5a8d4
TL
13#include <boost/beast/core/error.hpp>
14#include <boost/beast/core/detail/tuple.hpp>
b32b8144
FG
15#include <boost/asio/associated_allocator.hpp>
16#include <boost/asio/associated_executor.hpp>
92f5a8d4 17#include <boost/asio/handler_alloc_hook.hpp>
b32b8144 18#include <boost/asio/handler_continuation_hook.hpp>
11fdf7f2 19#include <boost/asio/handler_invoke_hook.hpp>
b32b8144 20#include <boost/core/ignore_unused.hpp>
92f5a8d4 21#include <boost/mp11/integer_sequence.hpp>
11fdf7f2 22#include <boost/is_placeholder.hpp>
b32b8144 23#include <functional>
92f5a8d4 24#include <type_traits>
b32b8144
FG
25#include <utility>
26
27namespace boost {
28namespace beast {
29namespace detail {
30
92f5a8d4
TL
31//------------------------------------------------------------------------------
32//
33// bind_handler
34//
35//------------------------------------------------------------------------------
b32b8144 36
b32b8144 37template<class Handler, class... Args>
92f5a8d4 38class bind_wrapper
b32b8144 39{
92f5a8d4 40 using args_type = detail::tuple<Args...>;
b32b8144
FG
41
42 Handler h_;
43 args_type args_;
44
92f5a8d4
TL
45 template<class T, class Executor>
46 friend struct net::associated_executor;
47
48 template<class T, class Allocator>
49 friend struct net::associated_allocator;
50
b32b8144
FG
51 template<class Arg, class Vals>
52 static
53 typename std::enable_if<
54 std::is_placeholder<typename
11fdf7f2
TL
55 std::decay<Arg>::type>::value == 0 &&
56 boost::is_placeholder<typename
b32b8144 57 std::decay<Arg>::type>::value == 0,
11fdf7f2 58 Arg&&>::type
92f5a8d4 59 extract(Arg&& arg, Vals&& vals)
b32b8144
FG
60 {
61 boost::ignore_unused(vals);
92f5a8d4 62 return std::forward<Arg>(arg);
b32b8144
FG
63 }
64
65 template<class Arg, class Vals>
66 static
67 typename std::enable_if<
68 std::is_placeholder<typename
69 std::decay<Arg>::type>::value != 0,
92f5a8d4
TL
70 tuple_element<std::is_placeholder<
71 typename std::decay<Arg>::type>::value - 1,
72 Vals>>::type&&
b32b8144
FG
73 extract(Arg&&, Vals&& vals)
74 {
92f5a8d4 75 return detail::get<std::is_placeholder<
b32b8144
FG
76 typename std::decay<Arg>::type>::value - 1>(
77 std::forward<Vals>(vals));
78 }
79
11fdf7f2
TL
80 template<class Arg, class Vals>
81 static
82 typename std::enable_if<
83 boost::is_placeholder<typename
84 std::decay<Arg>::type>::value != 0,
92f5a8d4
TL
85 tuple_element<boost::is_placeholder<
86 typename std::decay<Arg>::type>::value - 1,
87 Vals>>::type&&
11fdf7f2
TL
88 extract(Arg&&, Vals&& vals)
89 {
92f5a8d4 90 return detail::get<boost::is_placeholder<
11fdf7f2
TL
91 typename std::decay<Arg>::type>::value - 1>(
92 std::forward<Vals>(vals));
93 }
94
92f5a8d4 95 template<class ArgsTuple, std::size_t... S>
b32b8144
FG
96 static
97 void
98 invoke(
99 Handler& h,
100 ArgsTuple& args,
92f5a8d4
TL
101 tuple<>&&,
102 mp11::index_sequence<S...>)
b32b8144
FG
103 {
104 boost::ignore_unused(args);
92f5a8d4 105 h(detail::get<S>(std::move(args))...);
b32b8144
FG
106 }
107
108 template<
109 class ArgsTuple,
110 class ValsTuple,
111 std::size_t... S>
112 static
113 void
114 invoke(
115 Handler& h,
116 ArgsTuple& args,
117 ValsTuple&& vals,
92f5a8d4 118 mp11::index_sequence<S...>)
b32b8144
FG
119 {
120 boost::ignore_unused(args);
121 boost::ignore_unused(vals);
92f5a8d4 122 h(extract(detail::get<S>(std::move(args)),
b32b8144
FG
123 std::forward<ValsTuple>(vals))...);
124 }
125
126public:
92f5a8d4 127 using result_type = void; // asio needs this
b32b8144 128
92f5a8d4
TL
129 bind_wrapper(bind_wrapper&&) = default;
130 bind_wrapper(bind_wrapper const&) = default;
b32b8144 131
92f5a8d4
TL
132 template<
133 class DeducedHandler,
134 class... Args_>
b32b8144 135 explicit
92f5a8d4
TL
136 bind_wrapper(
137 DeducedHandler&& handler,
138 Args_&&... args)
b32b8144 139 : h_(std::forward<DeducedHandler>(handler))
92f5a8d4
TL
140 , args_(std::forward<Args_>(args)...)
141 {
142 }
143
144 template<class... Values>
145 void
146 operator()(Values&&... values)
b32b8144 147 {
92f5a8d4
TL
148 invoke(h_, args_,
149 tuple<Values&&...>(
150 std::forward<Values>(values)...),
151 mp11::index_sequence_for<Args...>());
b32b8144
FG
152 }
153
92f5a8d4
TL
154 //
155
156 template<class Function>
157 friend
158 void asio_handler_invoke(
159 Function&& f, bind_wrapper* op)
b32b8144 160 {
92f5a8d4
TL
161 using net::asio_handler_invoke;
162 asio_handler_invoke(f, std::addressof(op->h_));
b32b8144
FG
163 }
164
165 friend
92f5a8d4
TL
166 bool asio_handler_is_continuation(
167 bind_wrapper* op)
b32b8144 168 {
92f5a8d4
TL
169 using net::asio_handler_is_continuation;
170 return asio_handler_is_continuation(
171 std::addressof(op->h_));
b32b8144
FG
172 }
173
11fdf7f2 174 friend
92f5a8d4
TL
175 void* asio_handler_allocate(
176 std::size_t size, bind_wrapper* op)
11fdf7f2 177 {
92f5a8d4
TL
178 using net::asio_handler_allocate;
179 return asio_handler_allocate(
180 size, std::addressof(op->h_));
11fdf7f2
TL
181 }
182
92f5a8d4
TL
183 friend
184 void asio_handler_deallocate(
185 void* p, std::size_t size, bind_wrapper* op)
186 {
187 using net::asio_handler_deallocate;
188 asio_handler_deallocate(
189 p, size, std::addressof(op->h_));
190 }
191};
192
193template<class Handler, class... Args>
194class bind_back_wrapper;
195
196template<class Handler, class... Args>
197class bind_front_wrapper;
198
199//------------------------------------------------------------------------------
200//
201// bind_front
202//
203//------------------------------------------------------------------------------
204
205template<class Handler, class... Args>
206class bind_front_wrapper
207{
208 Handler h_;
209 detail::tuple<Args...> args_;
210
211 template<class T, class Executor>
212 friend struct net::associated_executor;
213
214 template<class T, class Allocator>
215 friend struct net::associated_allocator;
216
217 template<std::size_t... I, class... Ts>
b32b8144 218 void
92f5a8d4
TL
219 invoke(
220 std::false_type,
221 mp11::index_sequence<I...>,
222 Ts&&... ts)
b32b8144 223 {
92f5a8d4
TL
224 h_( detail::get<I>(std::move(args_))...,
225 std::forward<Ts>(ts)...);
b32b8144
FG
226 }
227
92f5a8d4 228 template<std::size_t... I, class... Ts>
b32b8144 229 void
92f5a8d4
TL
230 invoke(
231 std::true_type,
232 mp11::index_sequence<I...>,
233 Ts&&... ts)
b32b8144 234 {
92f5a8d4
TL
235 std::mem_fn(h_)(
236 detail::get<I>(std::move(args_))...,
237 std::forward<Ts>(ts)...);
238 }
239
240public:
241 using result_type = void; // asio needs this
242
243 bind_front_wrapper(bind_front_wrapper&&) = default;
244 bind_front_wrapper(bind_front_wrapper const&) = default;
245
246 template<class Handler_, class... Args_>
247 bind_front_wrapper(
248 Handler_&& handler,
249 Args_&&... args)
250 : h_(std::forward<Handler_>(handler))
251 , args_(std::forward<Args_>(args)...)
252 {
253 }
254
255 template<class... Ts>
256 void operator()(Ts&&... ts)
257 {
258 invoke(
259 std::is_member_function_pointer<Handler>{},
260 mp11::index_sequence_for<Args...>{},
261 std::forward<Ts>(ts)...);
262 }
263
264 //
265
266 template<class Function>
267 friend
268 void asio_handler_invoke(
269 Function&& f, bind_front_wrapper* op)
270 {
271 using net::asio_handler_invoke;
272 asio_handler_invoke(f, std::addressof(op->h_));
273 }
274
275 friend
276 bool asio_handler_is_continuation(
277 bind_front_wrapper* op)
278 {
279 using net::asio_handler_is_continuation;
280 return asio_handler_is_continuation(
281 std::addressof(op->h_));
282 }
283
284 friend
285 void* asio_handler_allocate(
286 std::size_t size, bind_front_wrapper* op)
287 {
288 using net::asio_handler_allocate;
289 return asio_handler_allocate(
290 size, std::addressof(op->h_));
291 }
292
293 friend
294 void asio_handler_deallocate(
295 void* p, std::size_t size, bind_front_wrapper* op)
296 {
297 using net::asio_handler_deallocate;
298 asio_handler_deallocate(
299 p, size, std::addressof(op->h_));
b32b8144
FG
300 }
301};
302
303} // detail
304} // beast
92f5a8d4 305} // boost
b32b8144 306
92f5a8d4
TL
307//------------------------------------------------------------------------------
308
309namespace boost {
b32b8144 310namespace asio {
92f5a8d4 311
b32b8144
FG
312template<class Handler, class... Args, class Executor>
313struct associated_executor<
92f5a8d4 314 beast::detail::bind_wrapper<Handler, Args...>, Executor>
b32b8144
FG
315{
316 using type = typename
317 associated_executor<Handler, Executor>::type;
318
319 static
320 type
92f5a8d4
TL
321 get(beast::detail::bind_wrapper<Handler, Args...> const& op,
322 Executor const& ex = Executor{}) noexcept
b32b8144
FG
323 {
324 return associated_executor<
92f5a8d4 325 Handler, Executor>::get(op.h_, ex);
b32b8144
FG
326 }
327};
b32b8144 328
92f5a8d4
TL
329template<class Handler, class... Args, class Executor>
330struct associated_executor<
331 beast::detail::bind_front_wrapper<Handler, Args...>, Executor>
332{
333 using type = typename
334 associated_executor<Handler, Executor>::type;
335
336 static
337 type
338 get(beast::detail::bind_front_wrapper<Handler, Args...> const& op,
339 Executor const& ex = Executor{}) noexcept
340 {
341 return associated_executor<
342 Handler, Executor>::get(op.h_, ex);
343 }
344};
345
346//
347
348template<class Handler, class... Args, class Allocator>
349struct associated_allocator<
350 beast::detail::bind_wrapper<Handler, Args...>, Allocator>
351{
352 using type = typename
353 associated_allocator<Handler, Allocator>::type;
354
355 static
356 type
357 get(beast::detail::bind_wrapper<Handler, Args...> const& op,
358 Allocator const& alloc = Allocator{}) noexcept
359 {
360 return associated_allocator<
361 Handler, Allocator>::get(op.h_, alloc);
362 }
363};
364
365template<class Handler, class... Args, class Allocator>
366struct associated_allocator<
367 beast::detail::bind_front_wrapper<Handler, Args...>, Allocator>
368{
369 using type = typename
370 associated_allocator<Handler, Allocator>::type;
371
372 static
373 type
374 get(beast::detail::bind_front_wrapper<Handler, Args...> const& op,
375 Allocator const& alloc = Allocator{}) noexcept
376 {
377 return associated_allocator<
378 Handler, Allocator>::get(op.h_, alloc);
379 }
380};
381
382} // asio
b32b8144
FG
383} // boost
384
92f5a8d4
TL
385//------------------------------------------------------------------------------
386
b32b8144 387namespace std {
92f5a8d4
TL
388
389// VFALCO Using std::bind on a completion handler will
390// cause undefined behavior later, because the executor
391// associated with the handler is not propagated to the
392// wrapper returned by std::bind; these overloads are
393// deleted to prevent mistakes. If this creates a problem
394// please contact me.
395
b32b8144
FG
396template<class Handler, class... Args>
397void
92f5a8d4 398bind(boost::beast::detail::bind_wrapper<
b32b8144 399 Handler, Args...>, ...) = delete;
92f5a8d4
TL
400
401template<class Handler, class... Args>
402void
403bind(boost::beast::detail::bind_front_wrapper<
404 Handler, Args...>, ...) = delete;
405
b32b8144
FG
406} // std
407
92f5a8d4
TL
408//------------------------------------------------------------------------------
409
b32b8144 410#endif