io_uring_socket_service_base.ipp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. //
  2. // detail/io_uring_socket_service_base.ipp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2024 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_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP
  11. #define BOOST_ASIO_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP
  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. #if defined(BOOST_ASIO_HAS_IO_URING)
  17. #include <boost/asio/detail/io_uring_socket_service_base.hpp>
  18. #include <boost/asio/detail/push_options.hpp>
  19. namespace boost {
  20. namespace asio {
  21. namespace detail {
  22. io_uring_socket_service_base::io_uring_socket_service_base(
  23. execution_context& context)
  24. : io_uring_service_(boost::asio::use_service<io_uring_service>(context))
  25. {
  26. io_uring_service_.init_task();
  27. }
  28. void io_uring_socket_service_base::base_shutdown()
  29. {
  30. }
  31. void io_uring_socket_service_base::construct(
  32. io_uring_socket_service_base::base_implementation_type& impl)
  33. {
  34. impl.socket_ = invalid_socket;
  35. impl.state_ = 0;
  36. impl.io_object_data_ = 0;
  37. }
  38. void io_uring_socket_service_base::base_move_construct(
  39. io_uring_socket_service_base::base_implementation_type& impl,
  40. io_uring_socket_service_base::base_implementation_type& other_impl)
  41. noexcept
  42. {
  43. impl.socket_ = other_impl.socket_;
  44. other_impl.socket_ = invalid_socket;
  45. impl.state_ = other_impl.state_;
  46. other_impl.state_ = 0;
  47. impl.io_object_data_ = other_impl.io_object_data_;
  48. other_impl.io_object_data_ = 0;
  49. }
  50. void io_uring_socket_service_base::base_move_assign(
  51. io_uring_socket_service_base::base_implementation_type& impl,
  52. io_uring_socket_service_base& /*other_service*/,
  53. io_uring_socket_service_base::base_implementation_type& other_impl)
  54. {
  55. destroy(impl);
  56. impl.socket_ = other_impl.socket_;
  57. other_impl.socket_ = invalid_socket;
  58. impl.state_ = other_impl.state_;
  59. other_impl.state_ = 0;
  60. impl.io_object_data_ = other_impl.io_object_data_;
  61. other_impl.io_object_data_ = 0;
  62. }
  63. void io_uring_socket_service_base::destroy(
  64. io_uring_socket_service_base::base_implementation_type& impl)
  65. {
  66. if (impl.socket_ != invalid_socket)
  67. {
  68. BOOST_ASIO_HANDLER_OPERATION((io_uring_service_.context(),
  69. "socket", &impl, impl.socket_, "close"));
  70. io_uring_service_.deregister_io_object(impl.io_object_data_);
  71. boost::system::error_code ignored_ec;
  72. socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
  73. io_uring_service_.cleanup_io_object(impl.io_object_data_);
  74. }
  75. }
  76. boost::system::error_code io_uring_socket_service_base::close(
  77. io_uring_socket_service_base::base_implementation_type& impl,
  78. boost::system::error_code& ec)
  79. {
  80. if (is_open(impl))
  81. {
  82. BOOST_ASIO_HANDLER_OPERATION((io_uring_service_.context(),
  83. "socket", &impl, impl.socket_, "close"));
  84. io_uring_service_.deregister_io_object(impl.io_object_data_);
  85. socket_ops::close(impl.socket_, impl.state_, false, ec);
  86. io_uring_service_.cleanup_io_object(impl.io_object_data_);
  87. }
  88. else
  89. {
  90. ec = success_ec_;
  91. }
  92. // The descriptor is closed by the OS even if close() returns an error.
  93. //
  94. // (Actually, POSIX says the state of the descriptor is unspecified. On
  95. // Linux the descriptor is apparently closed anyway; e.g. see
  96. // http://lkml.org/lkml/2005/9/10/129
  97. construct(impl);
  98. return ec;
  99. }
  100. socket_type io_uring_socket_service_base::release(
  101. io_uring_socket_service_base::base_implementation_type& impl,
  102. boost::system::error_code& ec)
  103. {
  104. if (!is_open(impl))
  105. {
  106. ec = boost::asio::error::bad_descriptor;
  107. return invalid_socket;
  108. }
  109. BOOST_ASIO_HANDLER_OPERATION((io_uring_service_.context(),
  110. "socket", &impl, impl.socket_, "release"));
  111. io_uring_service_.deregister_io_object(impl.io_object_data_);
  112. io_uring_service_.cleanup_io_object(impl.io_object_data_);
  113. socket_type sock = impl.socket_;
  114. construct(impl);
  115. ec = success_ec_;
  116. return sock;
  117. }
  118. boost::system::error_code io_uring_socket_service_base::cancel(
  119. io_uring_socket_service_base::base_implementation_type& impl,
  120. boost::system::error_code& ec)
  121. {
  122. if (!is_open(impl))
  123. {
  124. ec = boost::asio::error::bad_descriptor;
  125. return ec;
  126. }
  127. BOOST_ASIO_HANDLER_OPERATION((io_uring_service_.context(),
  128. "socket", &impl, impl.socket_, "cancel"));
  129. io_uring_service_.cancel_ops(impl.io_object_data_);
  130. ec = success_ec_;
  131. return ec;
  132. }
  133. boost::system::error_code io_uring_socket_service_base::do_open(
  134. io_uring_socket_service_base::base_implementation_type& impl,
  135. int af, int type, int protocol, boost::system::error_code& ec)
  136. {
  137. if (is_open(impl))
  138. {
  139. ec = boost::asio::error::already_open;
  140. return ec;
  141. }
  142. socket_holder sock(socket_ops::socket(af, type, protocol, ec));
  143. if (sock.get() == invalid_socket)
  144. return ec;
  145. io_uring_service_.register_io_object(impl.io_object_data_);
  146. impl.socket_ = sock.release();
  147. switch (type)
  148. {
  149. case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
  150. case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
  151. default: impl.state_ = 0; break;
  152. }
  153. ec = success_ec_;
  154. return ec;
  155. }
  156. boost::system::error_code io_uring_socket_service_base::do_assign(
  157. io_uring_socket_service_base::base_implementation_type& impl, int type,
  158. const io_uring_socket_service_base::native_handle_type& native_socket,
  159. boost::system::error_code& ec)
  160. {
  161. if (is_open(impl))
  162. {
  163. ec = boost::asio::error::already_open;
  164. return ec;
  165. }
  166. io_uring_service_.register_io_object(impl.io_object_data_);
  167. impl.socket_ = native_socket;
  168. switch (type)
  169. {
  170. case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
  171. case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
  172. default: impl.state_ = 0; break;
  173. }
  174. impl.state_ |= socket_ops::possible_dup;
  175. ec = success_ec_;
  176. return ec;
  177. }
  178. void io_uring_socket_service_base::start_op(
  179. io_uring_socket_service_base::base_implementation_type& impl,
  180. int op_type, io_uring_operation* op, bool is_continuation, bool noop)
  181. {
  182. if (!noop)
  183. {
  184. io_uring_service_.start_op(op_type,
  185. impl.io_object_data_, op, is_continuation);
  186. }
  187. else
  188. {
  189. io_uring_service_.post_immediate_completion(op, is_continuation);
  190. }
  191. }
  192. void io_uring_socket_service_base::start_accept_op(
  193. io_uring_socket_service_base::base_implementation_type& impl,
  194. io_uring_operation* op, bool is_continuation, bool peer_is_open)
  195. {
  196. if (!peer_is_open)
  197. start_op(impl, io_uring_service::read_op, op, is_continuation, false);
  198. else
  199. {
  200. op->ec_ = boost::asio::error::already_open;
  201. io_uring_service_.post_immediate_completion(op, is_continuation);
  202. }
  203. }
  204. } // namespace detail
  205. } // namespace asio
  206. } // namespace boost
  207. #include <boost/asio/detail/pop_options.hpp>
  208. #endif // defined(BOOST_ASIO_HAS_IO_URING)
  209. #endif // BOOST_ASIO_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP