File indexing completed on 2025-01-18 09:29:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
0011 #define BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
0012
0013 #include <boost/beast/core/error.hpp>
0014 #include <boost/beast/core/detail/tuple.hpp>
0015 #include <boost/asio/associated_allocator.hpp>
0016 #include <boost/asio/associated_cancellation_slot.hpp>
0017 #include <boost/asio/associated_executor.hpp>
0018 #include <boost/asio/handler_continuation_hook.hpp>
0019 #include <boost/core/ignore_unused.hpp>
0020 #include <boost/mp11/integer_sequence.hpp>
0021 #include <boost/bind/std_placeholders.hpp>
0022 #include <boost/is_placeholder.hpp>
0023 #include <functional>
0024 #include <type_traits>
0025 #include <utility>
0026
0027 namespace boost {
0028 namespace beast {
0029 namespace detail {
0030
0031
0032
0033
0034
0035
0036
0037 template<class Handler, class... Args>
0038 class bind_wrapper
0039 {
0040 using args_type = detail::tuple<Args...>;
0041
0042 Handler h_;
0043 args_type args_;
0044
0045 template<class T, class Executor>
0046 friend struct net::associated_executor;
0047
0048 template<class T, class Allocator>
0049 friend struct net::associated_allocator;
0050
0051 template<class T, class CancellationSlot>
0052 friend struct net::associated_cancellation_slot;
0053
0054 template<class Arg, class Vals>
0055 static
0056 typename std::enable_if<
0057 std::is_placeholder<typename
0058 std::decay<Arg>::type>::value == 0 &&
0059 boost::is_placeholder<typename
0060 std::decay<Arg>::type>::value == 0,
0061 Arg&&>::type
0062 extract(Arg&& arg, Vals&& vals)
0063 {
0064 boost::ignore_unused(vals);
0065 return std::forward<Arg>(arg);
0066 }
0067
0068 template<class Arg, class Vals>
0069 static
0070 typename std::enable_if<
0071 std::is_placeholder<typename
0072 std::decay<Arg>::type>::value != 0,
0073 tuple_element<std::is_placeholder<
0074 typename std::decay<Arg>::type>::value - 1,
0075 Vals>>::type&&
0076 extract(Arg&&, Vals&& vals)
0077 {
0078 return detail::get<std::is_placeholder<
0079 typename std::decay<Arg>::type>::value - 1>(
0080 std::forward<Vals>(vals));
0081 }
0082
0083 template<class Arg, class Vals>
0084 static
0085 typename std::enable_if<
0086 boost::is_placeholder<typename
0087 std::decay<Arg>::type>::value != 0 &&
0088 std::is_placeholder<typename
0089 std::decay<Arg>::type>::value == 0,
0090 tuple_element<boost::is_placeholder<
0091 typename std::decay<Arg>::type>::value - 1,
0092 Vals>>::type&&
0093 extract(Arg&&, Vals&& vals)
0094 {
0095 return detail::get<boost::is_placeholder<
0096 typename std::decay<Arg>::type>::value - 1>(
0097 std::forward<Vals>(vals));
0098 }
0099
0100 template<class ArgsTuple, std::size_t... S>
0101 static
0102 void
0103 invoke(
0104 Handler& h,
0105 ArgsTuple& args,
0106 tuple<>&&,
0107 mp11::index_sequence<S...>)
0108 {
0109 boost::ignore_unused(args);
0110 h(detail::get<S>(std::move(args))...);
0111 }
0112
0113 template<
0114 class ArgsTuple,
0115 class ValsTuple,
0116 std::size_t... S>
0117 static
0118 void
0119 invoke(
0120 Handler& h,
0121 ArgsTuple& args,
0122 ValsTuple&& vals,
0123 mp11::index_sequence<S...>)
0124 {
0125 boost::ignore_unused(args);
0126 boost::ignore_unused(vals);
0127 h(extract(detail::get<S>(std::move(args)),
0128 std::forward<ValsTuple>(vals))...);
0129 }
0130
0131 public:
0132 using result_type = void;
0133
0134 bind_wrapper(bind_wrapper&&) = default;
0135 bind_wrapper(bind_wrapper const&) = default;
0136
0137 template<
0138 class DeducedHandler,
0139 class... Args_>
0140 explicit
0141 bind_wrapper(
0142 DeducedHandler&& handler,
0143 Args_&&... args)
0144 : h_(std::forward<DeducedHandler>(handler))
0145 , args_(std::forward<Args_>(args)...)
0146 {
0147 }
0148
0149 template<class... Values>
0150 void
0151 operator()(Values&&... values)
0152 {
0153 invoke(h_, args_,
0154 tuple<Values&&...>(
0155 std::forward<Values>(values)...),
0156 mp11::index_sequence_for<Args...>());
0157 }
0158
0159
0160
0161 friend
0162 bool asio_handler_is_continuation(
0163 bind_wrapper* op)
0164 {
0165 using boost::asio::asio_handler_is_continuation;
0166 return asio_handler_is_continuation(
0167 std::addressof(op->h_));
0168 }
0169 };
0170
0171 template<class Handler, class... Args>
0172 class bind_back_wrapper;
0173
0174 template<class Handler, class... Args>
0175 class bind_front_wrapper;
0176
0177
0178
0179
0180
0181
0182
0183 template<class Handler, class... Args>
0184 class bind_front_wrapper
0185 {
0186 Handler h_;
0187 detail::tuple<Args...> args_;
0188
0189 template<class T, class Executor>
0190 friend struct net::associated_executor;
0191
0192 template<class T, class Allocator>
0193 friend struct net::associated_allocator;
0194
0195 template<class T, class CancellationSlot>
0196 friend struct net::associated_cancellation_slot;
0197
0198
0199 template<std::size_t... I, class... Ts>
0200 void
0201 invoke(
0202 std::false_type,
0203 mp11::index_sequence<I...>,
0204 Ts&&... ts)
0205 {
0206 h_( detail::get<I>(std::move(args_))...,
0207 std::forward<Ts>(ts)...);
0208 }
0209
0210 template<std::size_t... I, class... Ts>
0211 void
0212 invoke(
0213 std::true_type,
0214 mp11::index_sequence<I...>,
0215 Ts&&... ts)
0216 {
0217 std::mem_fn(h_)(
0218 detail::get<I>(std::move(args_))...,
0219 std::forward<Ts>(ts)...);
0220 }
0221
0222 public:
0223 using result_type = void;
0224
0225 bind_front_wrapper(bind_front_wrapper&&) = default;
0226 bind_front_wrapper(bind_front_wrapper const&) = default;
0227
0228 template<class Handler_, class... Args_>
0229 bind_front_wrapper(
0230 Handler_&& handler,
0231 Args_&&... args)
0232 : h_(std::forward<Handler_>(handler))
0233 , args_(std::forward<Args_>(args)...)
0234 {
0235 }
0236
0237 template<class... Ts>
0238 void operator()(Ts&&... ts)
0239 {
0240 invoke(
0241 std::is_member_function_pointer<Handler>{},
0242 mp11::index_sequence_for<Args...>{},
0243 std::forward<Ts>(ts)...);
0244 }
0245
0246
0247
0248 friend
0249 bool asio_handler_is_continuation(
0250 bind_front_wrapper* op)
0251 {
0252 using boost::asio::asio_handler_is_continuation;
0253 return asio_handler_is_continuation(
0254 std::addressof(op->h_));
0255 }
0256 };
0257
0258 }
0259 }
0260 }
0261
0262
0263
0264 namespace boost {
0265 namespace asio {
0266
0267 template<class Handler, class... Args, class Executor>
0268 struct associated_executor<
0269 beast::detail::bind_wrapper<Handler, Args...>, Executor>
0270 {
0271 using type = typename
0272 associated_executor<Handler, Executor>::type;
0273
0274 static
0275 type
0276 get(beast::detail::bind_wrapper<Handler, Args...> const& op,
0277 Executor const& ex = Executor{}) noexcept
0278 {
0279 return associated_executor<
0280 Handler, Executor>::get(op.h_, ex);
0281 }
0282 };
0283
0284 template<class Handler, class... Args, class Executor>
0285 struct associated_executor<
0286 beast::detail::bind_front_wrapper<Handler, Args...>, Executor>
0287 {
0288 using type = typename
0289 associated_executor<Handler, Executor>::type;
0290
0291 static
0292 type
0293 get(beast::detail::bind_front_wrapper<Handler, Args...> const& op,
0294 Executor const& ex = Executor{}) noexcept
0295 {
0296 return associated_executor<
0297 Handler, Executor>::get(op.h_, ex);
0298 }
0299 };
0300
0301
0302
0303 template<class Handler, class... Args, class Allocator>
0304 struct associated_allocator<
0305 beast::detail::bind_wrapper<Handler, Args...>, Allocator>
0306 {
0307 using type = typename
0308 associated_allocator<Handler, Allocator>::type;
0309
0310 static
0311 type
0312 get(beast::detail::bind_wrapper<Handler, Args...> const& op,
0313 Allocator const& alloc = Allocator{}) noexcept
0314 {
0315 return associated_allocator<
0316 Handler, Allocator>::get(op.h_, alloc);
0317 }
0318 };
0319
0320 template<class Handler, class... Args, class Allocator>
0321 struct associated_allocator<
0322 beast::detail::bind_front_wrapper<Handler, Args...>, Allocator>
0323 {
0324 using type = typename
0325 associated_allocator<Handler, Allocator>::type;
0326
0327 static
0328 type
0329 get(beast::detail::bind_front_wrapper<Handler, Args...> const& op,
0330 Allocator const& alloc = Allocator{}) noexcept
0331 {
0332 return associated_allocator<
0333 Handler, Allocator>::get(op.h_, alloc);
0334 }
0335 };
0336
0337 template<class Handler, class... Args, class CancellationSlot>
0338 struct associated_cancellation_slot<
0339 beast::detail::bind_wrapper<Handler, Args...>, CancellationSlot>
0340 {
0341 using type = typename
0342 associated_cancellation_slot<Handler>::type;
0343
0344 static
0345 type
0346 get(beast::detail::bind_wrapper<Handler, Args...> const& op,
0347 CancellationSlot const& slot = CancellationSlot{}) noexcept
0348 {
0349 return associated_cancellation_slot<
0350 Handler, CancellationSlot>::get(op.h_, slot);
0351 }
0352 };
0353
0354 template<class Handler, class... Args, class CancellationSlot>
0355 struct associated_cancellation_slot<
0356 beast::detail::bind_front_wrapper<Handler, Args...>, CancellationSlot>
0357 {
0358 using type = typename
0359 associated_cancellation_slot<Handler>::type;
0360
0361 static
0362 type
0363 get(beast::detail::bind_front_wrapper<Handler, Args...> const& op,
0364 CancellationSlot const& slot = CancellationSlot{}) noexcept
0365 {
0366 return associated_cancellation_slot<
0367 Handler, CancellationSlot>::get(op.h_, slot);
0368 }
0369 };
0370
0371
0372
0373 }
0374 }
0375
0376
0377
0378 namespace std {
0379
0380
0381
0382
0383
0384
0385
0386
0387 template<class Handler, class... Args>
0388 void
0389 bind(boost::beast::detail::bind_wrapper<
0390 Handler, Args...>, ...) = delete;
0391
0392 template<class Handler, class... Args>
0393 void
0394 bind(boost::beast::detail::bind_front_wrapper<
0395 Handler, Args...>, ...) = delete;
0396
0397 }
0398
0399
0400
0401 #endif