26 FdTable(io_uring &ring) : ring_(ring) {}
28 FdTable(
const FdTable &) =
delete;
29 FdTable &operator=(
const FdTable &) =
delete;
30 FdTable(FdTable &&) =
delete;
31 FdTable &operator=(FdTable &&) =
delete;
39 int init(
size_t capacity)
noexcept {
40 return io_uring_register_files_sparse(&ring_, capacity);
50 int init(
const int *fds,
unsigned nr_fds) {
51 return io_uring_register_files(&ring_, fds, nr_fds);
58 int destroy() noexcept {
return io_uring_unregister_files(&ring_); }
68 int update(
unsigned index_base,
const int *fds,
unsigned nr_fds)
noexcept {
69 return io_uring_register_files_update(&ring_, index_base, fds, nr_fds);
83 template <
typename Func>
84 [[deprecated(
"set_fd_accepter is deprecated and will be removed in a "
87 fd_accepter_ = std::forward<Func>(accepter);
97 return io_uring_register_file_alloc_range(&ring_, offset, size);
101 std::function<void(int32_t)> fd_accepter_ =
nullptr;
116 BufferTable(io_uring &ring) : ring_(ring) {}
118 BufferTable(
const BufferTable &) =
delete;
119 BufferTable &operator=(
const BufferTable &) =
delete;
120 BufferTable(BufferTable &&) =
delete;
121 BufferTable &operator=(BufferTable &&) =
delete;
129 int init(
size_t capacity)
noexcept {
130 int r = io_uring_register_buffers_sparse(&ring_, capacity);
145 int init(
const iovec *vecs,
unsigned nr_vecs) {
146 int r = io_uring_register_buffers(&ring_, vecs, nr_vecs);
159 initialized_ =
false;
160 return io_uring_unregister_buffers(&ring_);
171 int update(
unsigned index_base,
const iovec *vecs,
172 unsigned nr_vecs)
noexcept {
173 return io_uring_register_buffers_update_tag(&ring_, index_base, vecs,
177#if !IO_URING_CHECK_VERSION(2, 10)
188 unsigned int src_off = 0,
unsigned int nr = 0) noexcept {
189 auto *src_ring = &src.ring_;
190 auto *dst_ring = &ring_;
191 unsigned int flags = 0;
193 flags |= IORING_REGISTER_DST_REPLACE;
195 int r = __io_uring_clone_buffers_offset(dst_ring, src_ring, dst_off,
207 bool initialized_ =
false;
217 RingSettings(io_uring &ring) : ring_(ring) {}
221 io_uring_free_probe(probe_);
226 RingSettings(
const RingSettings &) =
delete;
227 RingSettings &operator=(
const RingSettings &) =
delete;
228 RingSettings(RingSettings &&) =
delete;
229 RingSettings &operator=(RingSettings &&) =
delete;
239 return io_uring_register_iowq_aff(&ring_, cpusz, mask);
246 return io_uring_unregister_iowq_aff(&ring_);
256 return io_uring_register_iowq_max_workers(&ring_, values);
268 probe_ = io_uring_get_probe_ring(&ring_);
278#if !IO_URING_CHECK_VERSION(2, 6)
285 return io_uring_register_napi(&ring_, napi);
292 return io_uring_unregister_napi(&ring_, napi);
296#if !IO_URING_CHECK_VERSION(2, 8)
302 int set_clock(io_uring_clock_register *clock_reg)
noexcept {
303 return io_uring_register_clock(&ring_, clock_reg);
307#if !IO_URING_CHECK_VERSION(2, 9)
314 return io_uring_resize_rings(&ring_, params);
318#if !IO_URING_CHECK_VERSION(2, 10)
325 return io_uring_set_iowait(&ring_, enable_iowait);
331 io_uring_probe *probe_ =
nullptr;
332 uint32_t features_ = 0;
340 ~Ring() { destroy(); }
342 Ring(
const Ring &) =
delete;
343 Ring &operator=(
const Ring &) =
delete;
344 Ring(Ring &&) =
delete;
345 Ring &operator=(Ring &&) =
delete;
348 int init(
unsigned int entries, io_uring_params *params,
349 [[maybe_unused]]
void *buf =
nullptr,
350 [[maybe_unused]]
size_t buf_size = 0) noexcept {
352 assert(!initialized_);
353#if !IO_URING_CHECK_VERSION(2, 5)
354 if (params->flags & IORING_SETUP_NO_MMAP) {
355 r = io_uring_queue_init_mem(entries, &ring_, params, buf, buf_size);
358 r = io_uring_queue_init_params(entries, &ring_, params);
362 settings_.features_ = params->features;
363 sqpoll_mode_ = (params->flags & IORING_SETUP_SQPOLL) != 0;
368 void destroy() noexcept {
370 io_uring_queue_exit(&ring_);
371 initialized_ =
false;
375 void submit() noexcept { io_uring_submit(&ring_); }
377 template <
typename Func>
378 size_t reap_completions_wait(Func &&process_func)
noexcept {
383 int r = io_uring_submit_and_wait(&ring_, 1);
384 if (r >= 0) [[likely]] {
386 }
else if (r == -EINTR) {
389 assert(
false &&
"io_uring_submit_and_wait failed");
393 io_uring_for_each_cqe(&ring_, head, cqe) {
395#if !IO_URING_CHECK_VERSION(2, 13)
396 reaped += io_uring_cqe_nr(cqe);
401 io_uring_cq_advance(&ring_, reaped);
405 template <
typename Func>
406 size_t reap_completions(Func &&process_func)
noexcept {
411 if (io_uring_peek_cqe(&ring_, &cqe) == 0) {
412 io_uring_for_each_cqe(&ring_, head, cqe) {
414#if !IO_URING_CHECK_VERSION(2, 13)
415 reaped += io_uring_cqe_nr(cqe);
420 io_uring_cq_advance(&ring_, reaped);
426 void reserve_space(
size_t n)
noexcept {
429 space_left = io_uring_sq_space_left(&ring_);
430 if (space_left >= n) {
437 io_uring *ring() noexcept {
return &ring_; }
439 FdTable &fd_table() noexcept {
return fd_table_; }
441 BufferTable &buffer_table() noexcept {
return buffer_table_; }
443 RingSettings &settings() noexcept {
return settings_; }
445 io_uring_sqe *get_sqe() noexcept {
return get_sqe_<io_uring_get_sqe>(); }
447#if !IO_URING_CHECK_VERSION(2, 13)
448 io_uring_sqe *get_sqe128() noexcept {
449 if (ring_.flags & (IORING_SETUP_SQE128 | IORING_SETUP_SQE_MIXED))
451 return get_sqe_<io_uring_get_sqe128>();
453 panic_on(
"SQE128 is not enabled for this io_uring ring");
459 template <io_uring_sqe *(*get_sqe)(struct io_uring *)>
460 io_uring_sqe *get_sqe_() noexcept {
461 [[maybe_unused]]
int r;
464 sqe = get_sqe(&ring_);
468 r = io_uring_submit(&ring_);
471 r = io_uring_sqring_wait(&ring_);
479 bool initialized_ =
false;
481 bool sqpoll_mode_ =
false;
483 FdTable fd_table_{ring_};
484 BufferTable buffer_table_{ring_};
485 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.
File descriptor table for io_uring.
void set_fd_accepter(Func &&accepter)
Set the accepter function for incoming file descriptors.
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.
friend auto async_fixed_fd_send(FdTable &dst, int source_fd, int target_fd, unsigned int flags)
See io_uring_prep_msg_ring_fd.
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.
Internal utility classes and functions used by Condy.