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