bind_handler.hpp 10 KB

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