basic_io_object.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. //
  2. // basic_io_object.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 ASIO_BASIC_IO_OBJECT_HPP
  11. #define ASIO_BASIC_IO_OBJECT_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #include "asio/io_context.hpp"
  17. #include "asio/detail/push_options.hpp"
  18. namespace asio {
  19. namespace detail
  20. {
  21. // Type trait used to determine whether a service supports move.
  22. template <typename IoObjectService>
  23. class service_has_move
  24. {
  25. private:
  26. typedef IoObjectService service_type;
  27. typedef typename service_type::implementation_type implementation_type;
  28. template <typename T, typename U>
  29. static auto asio_service_has_move_eval(T* t, U* u)
  30. -> decltype(t->move_construct(*u, *u), char());
  31. static char (&asio_service_has_move_eval(...))[2];
  32. public:
  33. static const bool value =
  34. sizeof(asio_service_has_move_eval(
  35. static_cast<service_type*>(0),
  36. static_cast<implementation_type*>(0))) == 1;
  37. };
  38. }
  39. /// Base class for all I/O objects.
  40. /**
  41. * @note All I/O objects are non-copyable. However, when using C++0x, certain
  42. * I/O objects do support move construction and move assignment.
  43. */
  44. #if defined(GENERATING_DOCUMENTATION)
  45. template <typename IoObjectService>
  46. #else
  47. template <typename IoObjectService,
  48. bool Movable = detail::service_has_move<IoObjectService>::value>
  49. #endif
  50. class basic_io_object
  51. {
  52. public:
  53. /// The type of the service that will be used to provide I/O operations.
  54. typedef IoObjectService service_type;
  55. /// The underlying implementation type of I/O object.
  56. typedef typename service_type::implementation_type implementation_type;
  57. #if !defined(ASIO_NO_DEPRECATED)
  58. /// (Deprecated: Use get_executor().) Get the io_context associated with the
  59. /// object.
  60. /**
  61. * This function may be used to obtain the io_context object that the I/O
  62. * object uses to dispatch handlers for asynchronous operations.
  63. *
  64. * @return A reference to the io_context object that the I/O object will use
  65. * to dispatch handlers. Ownership is not transferred to the caller.
  66. */
  67. asio::io_context& get_io_context()
  68. {
  69. return service_.get_io_context();
  70. }
  71. /// (Deprecated: Use get_executor().) Get the io_context associated with the
  72. /// object.
  73. /**
  74. * This function may be used to obtain the io_context object that the I/O
  75. * object uses to dispatch handlers for asynchronous operations.
  76. *
  77. * @return A reference to the io_context object that the I/O object will use
  78. * to dispatch handlers. Ownership is not transferred to the caller.
  79. */
  80. asio::io_context& get_io_service()
  81. {
  82. return service_.get_io_context();
  83. }
  84. #endif // !defined(ASIO_NO_DEPRECATED)
  85. /// The type of the executor associated with the object.
  86. typedef asio::io_context::executor_type executor_type;
  87. /// Get the executor associated with the object.
  88. executor_type get_executor() noexcept
  89. {
  90. return service_.get_io_context().get_executor();
  91. }
  92. protected:
  93. /// Construct a basic_io_object.
  94. /**
  95. * Performs:
  96. * @code get_service().construct(get_implementation()); @endcode
  97. */
  98. explicit basic_io_object(asio::io_context& io_context)
  99. : service_(asio::use_service<IoObjectService>(io_context))
  100. {
  101. service_.construct(implementation_);
  102. }
  103. #if defined(GENERATING_DOCUMENTATION)
  104. /// Move-construct a basic_io_object.
  105. /**
  106. * Performs:
  107. * @code get_service().move_construct(
  108. * get_implementation(), other.get_implementation()); @endcode
  109. *
  110. * @note Available only for services that support movability,
  111. */
  112. basic_io_object(basic_io_object&& other);
  113. /// Move-assign a basic_io_object.
  114. /**
  115. * Performs:
  116. * @code get_service().move_assign(get_implementation(),
  117. * other.get_service(), other.get_implementation()); @endcode
  118. *
  119. * @note Available only for services that support movability,
  120. */
  121. basic_io_object& operator=(basic_io_object&& other);
  122. /// Perform a converting move-construction of a basic_io_object.
  123. template <typename IoObjectService1>
  124. basic_io_object(IoObjectService1& other_service,
  125. typename IoObjectService1::implementation_type& other_implementation);
  126. #endif // defined(GENERATING_DOCUMENTATION)
  127. /// Protected destructor to prevent deletion through this type.
  128. /**
  129. * Performs:
  130. * @code get_service().destroy(get_implementation()); @endcode
  131. */
  132. ~basic_io_object()
  133. {
  134. service_.destroy(implementation_);
  135. }
  136. /// Get the service associated with the I/O object.
  137. service_type& get_service()
  138. {
  139. return service_;
  140. }
  141. /// Get the service associated with the I/O object.
  142. const service_type& get_service() const
  143. {
  144. return service_;
  145. }
  146. /// Get the underlying implementation of the I/O object.
  147. implementation_type& get_implementation()
  148. {
  149. return implementation_;
  150. }
  151. /// Get the underlying implementation of the I/O object.
  152. const implementation_type& get_implementation() const
  153. {
  154. return implementation_;
  155. }
  156. private:
  157. basic_io_object(const basic_io_object&);
  158. basic_io_object& operator=(const basic_io_object&);
  159. // The service associated with the I/O object.
  160. service_type& service_;
  161. /// The underlying implementation of the I/O object.
  162. implementation_type implementation_;
  163. };
  164. // Specialisation for movable objects.
  165. template <typename IoObjectService>
  166. class basic_io_object<IoObjectService, true>
  167. {
  168. public:
  169. typedef IoObjectService service_type;
  170. typedef typename service_type::implementation_type implementation_type;
  171. #if !defined(ASIO_NO_DEPRECATED)
  172. asio::io_context& get_io_context()
  173. {
  174. return service_->get_io_context();
  175. }
  176. asio::io_context& get_io_service()
  177. {
  178. return service_->get_io_context();
  179. }
  180. #endif // !defined(ASIO_NO_DEPRECATED)
  181. typedef asio::io_context::executor_type executor_type;
  182. executor_type get_executor() noexcept
  183. {
  184. return service_->get_io_context().get_executor();
  185. }
  186. protected:
  187. explicit basic_io_object(asio::io_context& io_context)
  188. : service_(&asio::use_service<IoObjectService>(io_context))
  189. {
  190. service_->construct(implementation_);
  191. }
  192. basic_io_object(basic_io_object&& other)
  193. : service_(&other.get_service())
  194. {
  195. service_->move_construct(implementation_, other.implementation_);
  196. }
  197. template <typename IoObjectService1>
  198. basic_io_object(IoObjectService1& other_service,
  199. typename IoObjectService1::implementation_type& other_implementation)
  200. : service_(&asio::use_service<IoObjectService>(
  201. other_service.get_io_context()))
  202. {
  203. service_->converting_move_construct(implementation_,
  204. other_service, other_implementation);
  205. }
  206. ~basic_io_object()
  207. {
  208. service_->destroy(implementation_);
  209. }
  210. basic_io_object& operator=(basic_io_object&& other)
  211. {
  212. service_->move_assign(implementation_,
  213. *other.service_, other.implementation_);
  214. service_ = other.service_;
  215. return *this;
  216. }
  217. service_type& get_service()
  218. {
  219. return *service_;
  220. }
  221. const service_type& get_service() const
  222. {
  223. return *service_;
  224. }
  225. implementation_type& get_implementation()
  226. {
  227. return implementation_;
  228. }
  229. const implementation_type& get_implementation() const
  230. {
  231. return implementation_;
  232. }
  233. private:
  234. basic_io_object(const basic_io_object&);
  235. void operator=(const basic_io_object&);
  236. IoObjectService* service_;
  237. implementation_type implementation_;
  238. };
  239. } // namespace asio
  240. #include "asio/detail/pop_options.hpp"
  241. #endif // ASIO_BASIC_IO_OBJECT_HPP