File indexing completed on 2025-01-18 09:28:39
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_OP_HPP
0012 #define BOOST_ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_OP_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019
0020 #if defined(BOOST_ASIO_HAS_IO_URING)
0021
0022 #include <boost/asio/detail/bind_handler.hpp>
0023 #include <boost/asio/detail/buffer_sequence_adapter.hpp>
0024 #include <boost/asio/detail/descriptor_ops.hpp>
0025 #include <boost/asio/detail/fenced_block.hpp>
0026 #include <boost/asio/detail/handler_work.hpp>
0027 #include <boost/asio/detail/io_uring_operation.hpp>
0028 #include <boost/asio/detail/memory.hpp>
0029
0030 #include <boost/asio/detail/push_options.hpp>
0031
0032 namespace boost {
0033 namespace asio {
0034 namespace detail {
0035
0036 template <typename MutableBufferSequence>
0037 class io_uring_descriptor_read_op_base : public io_uring_operation
0038 {
0039 public:
0040 io_uring_descriptor_read_op_base(const boost::system::error_code& success_ec,
0041 int descriptor, descriptor_ops::state_type state,
0042 const MutableBufferSequence& buffers, func_type complete_func)
0043 : io_uring_operation(success_ec,
0044 &io_uring_descriptor_read_op_base::do_prepare,
0045 &io_uring_descriptor_read_op_base::do_perform, complete_func),
0046 descriptor_(descriptor),
0047 state_(state),
0048 buffers_(buffers),
0049 bufs_(buffers)
0050 {
0051 }
0052
0053 static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)
0054 {
0055 BOOST_ASIO_ASSUME(base != 0);
0056 io_uring_descriptor_read_op_base* o(
0057 static_cast<io_uring_descriptor_read_op_base*>(base));
0058
0059 if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)
0060 {
0061 ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLIN);
0062 }
0063 else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer)
0064 {
0065 ::io_uring_prep_read_fixed(sqe, o->descriptor_,
0066 o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,
0067 0, o->bufs_.registered_id().native_handle());
0068 }
0069 else
0070 {
0071 ::io_uring_prep_readv(sqe, o->descriptor_,
0072 o->bufs_.buffers(), o->bufs_.count(), -1);
0073 }
0074 }
0075
0076 static bool do_perform(io_uring_operation* base, bool after_completion)
0077 {
0078 BOOST_ASIO_ASSUME(base != 0);
0079 io_uring_descriptor_read_op_base* o(
0080 static_cast<io_uring_descriptor_read_op_base*>(base));
0081
0082 if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)
0083 {
0084 if (o->bufs_.is_single_buffer)
0085 {
0086 return descriptor_ops::non_blocking_read1(
0087 o->descriptor_, o->bufs_.first(o->buffers_).data(),
0088 o->bufs_.first(o->buffers_).size(), o->ec_,
0089 o->bytes_transferred_);
0090 }
0091 else
0092 {
0093 return descriptor_ops::non_blocking_read(
0094 o->descriptor_, o->bufs_.buffers(), o->bufs_.count(),
0095 o->ec_, o->bytes_transferred_);
0096 }
0097 }
0098 else if (after_completion)
0099 {
0100 if (!o->ec_ && o->bytes_transferred_ == 0)
0101 o->ec_ = boost::asio::error::eof;
0102 }
0103
0104 if (o->ec_ && o->ec_ == boost::asio::error::would_block)
0105 {
0106 o->state_ |= descriptor_ops::internal_non_blocking;
0107 return false;
0108 }
0109
0110 return after_completion;
0111 }
0112
0113 private:
0114 int descriptor_;
0115 descriptor_ops::state_type state_;
0116 MutableBufferSequence buffers_;
0117 buffer_sequence_adapter<boost::asio::mutable_buffer,
0118 MutableBufferSequence> bufs_;
0119 };
0120
0121 template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
0122 class io_uring_descriptor_read_op
0123 : public io_uring_descriptor_read_op_base<MutableBufferSequence>
0124 {
0125 public:
0126 BOOST_ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_read_op);
0127
0128 io_uring_descriptor_read_op(const boost::system::error_code& success_ec,
0129 int descriptor, descriptor_ops::state_type state,
0130 const MutableBufferSequence& buffers,
0131 Handler& handler, const IoExecutor& io_ex)
0132 : io_uring_descriptor_read_op_base<MutableBufferSequence>(success_ec,
0133 descriptor, state, buffers, &io_uring_descriptor_read_op::do_complete),
0134 handler_(static_cast<Handler&&>(handler)),
0135 work_(handler_, io_ex)
0136 {
0137 }
0138
0139 static void do_complete(void* owner, operation* base,
0140 const boost::system::error_code& ,
0141 std::size_t )
0142 {
0143
0144 BOOST_ASIO_ASSUME(base != 0);
0145 io_uring_descriptor_read_op* o
0146 (static_cast<io_uring_descriptor_read_op*>(base));
0147 ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
0148
0149 BOOST_ASIO_HANDLER_COMPLETION((*o));
0150
0151
0152 handler_work<Handler, IoExecutor> w(
0153 static_cast<handler_work<Handler, IoExecutor>&&>(
0154 o->work_));
0155
0156 BOOST_ASIO_ERROR_LOCATION(o->ec_);
0157
0158
0159
0160
0161
0162
0163
0164 detail::binder2<Handler, boost::system::error_code, std::size_t>
0165 handler(o->handler_, o->ec_, o->bytes_transferred_);
0166 p.h = boost::asio::detail::addressof(handler.handler_);
0167 p.reset();
0168
0169
0170 if (owner)
0171 {
0172 fenced_block b(fenced_block::half);
0173 BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
0174 w.complete(handler, handler.handler_);
0175 BOOST_ASIO_HANDLER_INVOCATION_END;
0176 }
0177 }
0178
0179 private:
0180 Handler handler_;
0181 handler_work<Handler, IoExecutor> work_;
0182 };
0183
0184 }
0185 }
0186 }
0187
0188 #include <boost/asio/detail/pop_options.hpp>
0189
0190 #endif
0191
0192 #endif