25 FdTable(io_uring &ring) : ring_(ring) {}
27 FdTable(
const FdTable &) =
delete;
28 FdTable &operator=(
const FdTable &) =
delete;
29 FdTable(FdTable &&) =
delete;
30 FdTable &operator=(FdTable &&) =
delete;
38 int init(
size_t capacity)
noexcept {
39 return io_uring_register_files_sparse(&ring_, capacity);
49 int init(
const int *fds,
unsigned nr_fds) {
50 return io_uring_register_files(&ring_, fds, nr_fds);
57 int destroy() noexcept {
return io_uring_unregister_files(&ring_); }
67 int update(
unsigned index_base,
const int *fds,
unsigned nr_fds)
noexcept {
68 return io_uring_register_files_update(&ring_, index_base, fds, nr_fds);
78 return io_uring_register_file_alloc_range(&ring_, offset, size);
94 BufferTable(io_uring &ring) : ring_(ring) {}
96 BufferTable(
const BufferTable &) =
delete;
97 BufferTable &operator=(
const BufferTable &) =
delete;
98 BufferTable(BufferTable &&) =
delete;
99 BufferTable &operator=(BufferTable &&) =
delete;
107 int init(
size_t capacity)
noexcept {
108 int r = io_uring_register_buffers_sparse(&ring_, capacity);
123 int init(
const iovec *vecs,
unsigned nr_vecs) {
124 int r = io_uring_register_buffers(&ring_, vecs, nr_vecs);
137 initialized_ =
false;
138 return io_uring_unregister_buffers(&ring_);
149 int update(
unsigned index_base,
const iovec *vecs,
150 unsigned nr_vecs)
noexcept {
151 return io_uring_register_buffers_update_tag(&ring_, index_base, vecs,
155#if !IO_URING_CHECK_VERSION(2, 10)
166 unsigned int src_off = 0,
unsigned int nr = 0) noexcept {
167 auto *src_ring = &src.ring_;
168 auto *dst_ring = &ring_;
169 unsigned int flags = 0;
171 flags |= IORING_REGISTER_DST_REPLACE;
173 int r = __io_uring_clone_buffers_offset(dst_ring, src_ring, dst_off,
185 bool initialized_ =
false;
195 RingSettings(io_uring &ring) : ring_(ring) {}
199 io_uring_free_probe(probe_);
204 RingSettings(
const RingSettings &) =
delete;
205 RingSettings &operator=(
const RingSettings &) =
delete;
206 RingSettings(RingSettings &&) =
delete;
207 RingSettings &operator=(RingSettings &&) =
delete;
217 return io_uring_register_iowq_aff(&ring_, cpusz, mask);
224 return io_uring_unregister_iowq_aff(&ring_);
234 return io_uring_register_iowq_max_workers(&ring_, values);
246 probe_ = io_uring_get_probe_ring(&ring_);
256#if !IO_URING_CHECK_VERSION(2, 6)
263 return io_uring_register_napi(&ring_, napi);
270 return io_uring_unregister_napi(&ring_, napi);
274#if !IO_URING_CHECK_VERSION(2, 8)
280 int set_clock(io_uring_clock_register *clock_reg)
noexcept {
281 return io_uring_register_clock(&ring_, clock_reg);
285#if !IO_URING_CHECK_VERSION(2, 9)
292 return io_uring_resize_rings(&ring_, params);
296#if !IO_URING_CHECK_VERSION(2, 10)
303 return io_uring_set_iowait(&ring_, enable_iowait);
309 io_uring_probe *probe_ =
nullptr;
310 uint32_t features_ = 0;
318 ~Ring() { destroy(); }
320 Ring(
const Ring &) =
delete;
321 Ring &operator=(
const Ring &) =
delete;
322 Ring(Ring &&) =
delete;
323 Ring &operator=(Ring &&) =
delete;
326 int init(
unsigned int entries, io_uring_params *params,
327 [[maybe_unused]]
void *buf =
nullptr,
328 [[maybe_unused]]
size_t buf_size = 0) noexcept {
333#if !IO_URING_CHECK_VERSION(2, 5)
334 if (params->flags & IORING_SETUP_NO_MMAP) {
335 r = io_uring_queue_init_mem(entries, &ring_, params, buf, buf_size);
338 r = io_uring_queue_init_params(entries, &ring_, params);
342 settings_.features_ = params->features;
343 sqpoll_mode_ = (params->flags & IORING_SETUP_SQPOLL) != 0;
348 void destroy() noexcept {
350 io_uring_queue_exit(&ring_);
351 initialized_ =
false;
355 void submit() noexcept { io_uring_submit(&ring_); }
357 template <
typename Func>
358 ssize_t reap_completions_wait(Func &&process_func)
noexcept {
363 int r = io_uring_submit_and_wait(&ring_, 1);
364 if (r >= 0) [[likely]] {
366 }
else if (r == -EINTR) {
373 io_uring_for_each_cqe(&ring_, head, cqe) {
375#if !IO_URING_CHECK_VERSION(2, 13)
376 reaped += io_uring_cqe_nr(cqe);
381 io_uring_cq_advance(&ring_, reaped);
385 template <
typename Func>
386 ssize_t reap_completions(Func &&process_func)
noexcept {
388 int r = io_uring_peek_cqe(&ring_, &cqe);
397 io_uring_for_each_cqe(&ring_, head, cqe) {
399#if !IO_URING_CHECK_VERSION(2, 13)
400 reaped += io_uring_cqe_nr(cqe);
405 io_uring_cq_advance(&ring_, reaped);
409 void reserve_space(
size_t n)
noexcept {
412 space_left = io_uring_sq_space_left(&ring_);
413 if (space_left >= n) {
420 io_uring *ring() noexcept {
return &ring_; }
422 FdTable &fd_table() noexcept {
return fd_table_; }
424 BufferTable &buffer_table() noexcept {
return buffer_table_; }
426 RingSettings &settings() noexcept {
return settings_; }
428 io_uring_sqe *get_sqe() noexcept {
return get_sqe_<io_uring_get_sqe>(); }
430#if !IO_URING_CHECK_VERSION(2, 13)
431 io_uring_sqe *get_sqe128() noexcept {
432 if (ring_.flags & (IORING_SETUP_SQE128 | IORING_SETUP_SQE_MIXED))
434 return get_sqe_<io_uring_get_sqe128>();
441 template <io_uring_sqe *(*get_sqe)(struct io_uring *)>
442 io_uring_sqe *get_sqe_() noexcept {
443 [[maybe_unused]]
int r;
446 sqe = get_sqe(&ring_);
450 r = io_uring_submit(&ring_);
453 r = io_uring_sqring_wait(&ring_);
461 bool initialized_ =
false;
463 bool sqpoll_mode_ =
false;
465 FdTable fd_table_{ring_};
466 BufferTable buffer_table_{ring_};
467 RingSettings settings_{ring_};
int clone_buffers(BufferTable &src, unsigned int dst_off=0, unsigned int src_off=0, unsigned int nr=0) noexcept
Clone buffers from another BufferTable into this one.
int update(unsigned index_base, const iovec *vecs, unsigned nr_vecs) noexcept
Update the buffer table starting from the given index.
int init(size_t capacity) noexcept
Initialize the buffer table with the given capacity.
int destroy() noexcept
Destroy the buffer table.
int init(const iovec *vecs, unsigned nr_vecs)
Initialize the buffer table with the given array of iovec structures.
int init(size_t capacity) noexcept
Initialize the file descriptor table with the given capacity.
int destroy() noexcept
Destroy the file descriptor table.
int init(const int *fds, unsigned nr_fds)
Initialize the file descriptor table with the given array of file descriptors.
int set_file_alloc_range(unsigned offset, unsigned size) noexcept
Set the file allocation range for the fd table.
int update(unsigned index_base, const int *fds, unsigned nr_fds) noexcept
Update the file descriptor table starting from the given index.
int set_rings_size(io_uring_params *params) noexcept
Resize the rings of the io_uring instance.
int apply_napi(io_uring_napi *napi) noexcept
Apply NAPI settings to the io_uring instance.
io_uring_probe * get_probe() noexcept
Get the io_uring probe for the ring.
uint32_t get_features() const noexcept
Get the supported features of the ring.
int set_iowq_max_workers(unsigned int *values) noexcept
Set the maximum number of I/O workers.
int apply_iowq_aff(size_t cpusz, const cpu_set_t *mask) noexcept
Apply I/O worker queue affinity settings.
int remove_iowq_aff() noexcept
Remove I/O worker queue affinity settings.
int set_clock(io_uring_clock_register *clock_reg) noexcept
Set the clock registration for the io_uring instance.
int set_iowait(bool enable_iowait) noexcept
Enable or disable iowait for the io_uring instance.
int remove_napi(io_uring_napi *napi=nullptr) noexcept
Remove NAPI settings from the io_uring instance.
The event loop runtime for executing asynchronous.
The main namespace for the Condy library.