bind_handler.hpp 8.6 KB

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