channel_payload.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. //
  2. // experimental/detail/channel_payload.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_EXPERIMENTAL_DETAIL_CHANNEL_PAYLOAD_HPP
  11. #define BOOST_ASIO_EXPERIMENTAL_DETAIL_CHANNEL_PAYLOAD_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <boost/asio/detail/type_traits.hpp>
  17. #include <boost/system/error_code.hpp>
  18. #include <boost/asio/experimental/detail/channel_message.hpp>
  19. #if defined(BOOST_ASIO_HAS_STD_VARIANT)
  20. # include <variant>
  21. #else // defined(BOOST_ASIO_HAS_STD_VARIANT)
  22. # include <new>
  23. #endif // defined(BOOST_ASIO_HAS_STD_VARIANT)
  24. #include <boost/asio/detail/push_options.hpp>
  25. namespace boost {
  26. namespace asio {
  27. namespace experimental {
  28. namespace detail {
  29. template <typename... Signatures>
  30. class channel_payload;
  31. template <typename R>
  32. class channel_payload<R()>
  33. {
  34. public:
  35. explicit channel_payload(channel_message<R()>)
  36. {
  37. }
  38. template <typename Handler>
  39. void receive(Handler& handler)
  40. {
  41. static_cast<Handler&&>(handler)();
  42. }
  43. };
  44. template <typename Signature>
  45. class channel_payload<Signature>
  46. {
  47. public:
  48. channel_payload(channel_message<Signature>&& m)
  49. : message_(static_cast<channel_message<Signature>&&>(m))
  50. {
  51. }
  52. template <typename Handler>
  53. void receive(Handler& handler)
  54. {
  55. message_.receive(handler);
  56. }
  57. private:
  58. channel_message<Signature> message_;
  59. };
  60. #if defined(BOOST_ASIO_HAS_STD_VARIANT)
  61. template <typename... Signatures>
  62. class channel_payload
  63. {
  64. public:
  65. template <typename Signature>
  66. channel_payload(channel_message<Signature>&& m)
  67. : message_(static_cast<channel_message<Signature>&&>(m))
  68. {
  69. }
  70. template <typename Handler>
  71. void receive(Handler& handler)
  72. {
  73. std::visit(
  74. [&](auto& message)
  75. {
  76. message.receive(handler);
  77. }, message_);
  78. }
  79. private:
  80. std::variant<channel_message<Signatures>...> message_;
  81. };
  82. #else // defined(BOOST_ASIO_HAS_STD_VARIANT)
  83. template <typename R1, typename R2>
  84. class channel_payload<R1(), R2(boost::system::error_code)>
  85. {
  86. public:
  87. typedef channel_message<R1()> void_message_type;
  88. typedef channel_message<R2(boost::system::error_code)> error_message_type;
  89. channel_payload(void_message_type&&)
  90. : message_(0, boost::system::error_code()),
  91. empty_(true)
  92. {
  93. }
  94. channel_payload(error_message_type&& m)
  95. : message_(static_cast<error_message_type&&>(m)),
  96. empty_(false)
  97. {
  98. }
  99. template <typename Handler>
  100. void receive(Handler& handler)
  101. {
  102. if (empty_)
  103. channel_message<R1()>(0).receive(handler);
  104. else
  105. message_.receive(handler);
  106. }
  107. private:
  108. error_message_type message_;
  109. bool empty_;
  110. };
  111. template <typename Sig1, typename Sig2>
  112. class channel_payload<Sig1, Sig2>
  113. {
  114. public:
  115. typedef channel_message<Sig1> message_1_type;
  116. typedef channel_message<Sig2> message_2_type;
  117. channel_payload(message_1_type&& m)
  118. : index_(1)
  119. {
  120. new (&storage_.message_1_) message_1_type(static_cast<message_1_type&&>(m));
  121. }
  122. channel_payload(message_2_type&& m)
  123. : index_(2)
  124. {
  125. new (&storage_.message_2_) message_2_type(static_cast<message_2_type&&>(m));
  126. }
  127. channel_payload(channel_payload&& other)
  128. : index_(other.index_)
  129. {
  130. switch (index_)
  131. {
  132. case 1:
  133. new (&storage_.message_1_) message_1_type(
  134. static_cast<message_1_type&&>(other.storage_.message_1_));
  135. break;
  136. case 2:
  137. new (&storage_.message_2_) message_2_type(
  138. static_cast<message_2_type&&>(other.storage_.message_2_));
  139. break;
  140. default:
  141. break;
  142. }
  143. }
  144. ~channel_payload()
  145. {
  146. switch (index_)
  147. {
  148. case 1:
  149. storage_.message_1_.~message_1_type();
  150. break;
  151. case 2:
  152. storage_.message_2_.~message_2_type();
  153. break;
  154. default:
  155. break;
  156. }
  157. }
  158. template <typename Handler>
  159. void receive(Handler& handler)
  160. {
  161. switch (index_)
  162. {
  163. case 1:
  164. storage_.message_1_.receive(handler);
  165. break;
  166. case 2:
  167. storage_.message_2_.receive(handler);
  168. break;
  169. default:
  170. break;
  171. }
  172. }
  173. private:
  174. union storage
  175. {
  176. storage() {}
  177. ~storage() {}
  178. char dummy_;
  179. message_1_type message_1_;
  180. message_2_type message_2_;
  181. } storage_;
  182. unsigned char index_;
  183. };
  184. #endif // defined(BOOST_ASIO_HAS_STD_VARIANT)
  185. } // namespace detail
  186. } // namespace experimental
  187. } // namespace asio
  188. } // namespace boost
  189. #include <boost/asio/detail/pop_options.hpp>
  190. #endif // BOOST_ASIO_EXPERIMENTAL_DETAIL_CHANNEL_PAYLOAD_HPP