Condy v1.7.0
C++ Asynchronous System Call Layer for Linux
Loading...
Searching...
No Matches
ring.hpp
Go to the documentation of this file.
1
7
8#pragma once
9
10#include "condy/condy_uring.hpp"
11#include "condy/utils.hpp"
12#include <cassert>
13#include <cerrno>
14#include <cstddef>
15#include <cstring>
16
17namespace condy {
18
19class Ring {
20public:
21 Ring(unsigned int entries, io_uring_params *params,
22 [[maybe_unused]] void *buf, [[maybe_unused]] size_t buf_size,
23 size_t submit_batch)
24 : submit_batch_(submit_batch) {
25 int r;
26#if !IO_URING_CHECK_VERSION(2, 5) // >= 2.5
27 if (params->flags & IORING_SETUP_NO_MMAP) {
28 r = io_uring_queue_init_mem(entries, &ring_, params, buf, buf_size);
29 } else {
30 r = io_uring_queue_init_params(entries, &ring_, params);
31 }
32#else
33 r = io_uring_queue_init_params(entries, &ring_, params);
34#endif
35 if (r < 0) {
36 throw make_system_error("io_uring_queue_init_params", -r);
37 }
38 }
39
40 ~Ring() { io_uring_queue_exit(&ring_); }
41
42 CONDY_DELETE_COPY_MOVE(Ring);
43
44public:
45 void submit() noexcept {
46 maybe_submit_count_ = 0;
47 io_uring_submit(&ring_);
48 }
49
50 void maybe_submit() noexcept {
51 maybe_submit_count_++;
52 if (maybe_submit_count_ >= submit_batch_) {
53 submit();
54 }
55 }
56
57 template <typename Func>
58 ssize_t reap_completions_wait(Func &&process_func) noexcept {
59 unsigned head;
60 io_uring_cqe *cqe;
61 ssize_t reaped = 0;
62 do {
63 int r = io_uring_submit_and_wait(&ring_, 1);
64 if (r >= 0) [[likely]] {
65 maybe_submit_count_ = 0;
66 break;
67 } else if (r == -EINTR) {
68 continue;
69 } else {
70 return r;
71 }
72 } while (true);
73
74 io_uring_for_each_cqe(&ring_, head, cqe) {
75 process_func(cqe);
76#if !IO_URING_CHECK_VERSION(2, 13) // >= 2.13
77 reaped += io_uring_cqe_nr(cqe);
78#else
79 reaped++;
80#endif
81 }
82 io_uring_cq_advance(&ring_, reaped);
83 return reaped;
84 }
85
86 template <typename Func>
87 ssize_t reap_completions(Func &&process_func) noexcept {
88 io_uring_cqe *cqe;
89 int r = io_uring_peek_cqe(&ring_, &cqe);
90 if (r == -EAGAIN) {
91 return 0;
92 } else if (r < 0) {
93 return r;
94 }
95
96 unsigned head;
97 ssize_t reaped = 0;
98 io_uring_for_each_cqe(&ring_, head, cqe) {
99 process_func(cqe);
100#if !IO_URING_CHECK_VERSION(2, 13) // >= 2.13
101 reaped += io_uring_cqe_nr(cqe);
102#else
103 reaped++;
104#endif
105 }
106 io_uring_cq_advance(&ring_, reaped);
107 return reaped;
108 }
109
110 void reserve_space(size_t n) noexcept {
111 size_t space_left;
112 do {
113 space_left = io_uring_sq_space_left(&ring_);
114 if (space_left >= n) {
115 return;
116 }
117 submit();
118 } while (true);
119 }
120
121 io_uring *ring() noexcept { return &ring_; }
122
123 io_uring_sqe *get_sqe() noexcept { return get_sqe_<io_uring_get_sqe>(); }
124
125#if !IO_URING_CHECK_VERSION(2, 13) // >= 2.13
126 io_uring_sqe *get_sqe128() noexcept {
127 if (ring_.flags & (IORING_SETUP_SQE128 | IORING_SETUP_SQE_MIXED))
128 [[likely]] {
129 return get_sqe_<io_uring_get_sqe128>();
130 }
131 return nullptr;
132 }
133#endif
134
135private:
136 template <io_uring_sqe *(*get_sqe)(struct io_uring *)>
137 io_uring_sqe *get_sqe_() noexcept {
138 [[maybe_unused]] int r;
139 io_uring_sqe *sqe;
140 do {
141 sqe = get_sqe(&ring_);
142 if (sqe) {
143 break;
144 }
145 submit();
146 if (ring_.flags & IORING_SETUP_SQPOLL) {
147 r = io_uring_sqring_wait(&ring_);
148 assert(r >= 0);
149 }
150 } while (true);
151 return sqe;
152 }
153
154private:
155 io_uring ring_;
156 size_t submit_batch_;
157 size_t maybe_submit_count_ = 0;
158};
159
160} // namespace condy
The main namespace for the Condy library.
Definition condy.hpp:31
Internal utility classes and functions used by Condy.