20template <
typename T> T &&unwrap_fixed(T &&t)
noexcept {
21 return std::forward<T>(t);
24inline int unwrap_fixed(FixedFd fd)
noexcept {
return fd.value; }
26template <
typename Func,
typename... Args>
27auto make_op_awaiter(Func &&func, Args &&...args) {
28 auto prep_func = [func = std::forward<Func>(func),
30 unwrap_fixed(std::forward<Args>(args))](Ring *ring) {
31 auto *sqe = ring->get_sqe();
38#if CONDY_URING_VERSION_GE(2, 13)
39template <
typename Func,
typename... Args>
40auto make_op_awaiter128(Func &&func, Args &&...args) {
41 auto prep_func = [func = std::forward<Func>(func),
43 unwrap_fixed(std::forward<Args>(args))](Ring *ring) {
44 auto *sqe = ring->get_sqe128();
54template <
typename MultiShotFunc,
typename Func,
typename... Args>
55auto make_multishot_op_awaiter(MultiShotFunc &&multishot_func, Func &&func,
57 auto prep_func = [func = std::forward<Func>(func),
59 unwrap_fixed(std::forward<Args>(args))](Ring *ring) {
60 auto *sqe = ring->get_sqe();
65 std::move(prep_func), SimpleCQEHandler{},
66 std::forward<MultiShotFunc>(multishot_func));
69template <BufferRingLike Br,
typename Func,
typename... Args>
70auto make_select_buffer_op_awaiter(Br *buffers, Func &&func, Args &&...args) {
71 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
73 unwrap_fixed(std::forward<Args>(args))](Ring *ring) {
74 auto *sqe = ring->get_sqe();
76 sqe->flags |= IOSQE_BUFFER_SELECT;
77 sqe->buf_group = bgid;
81 SelectBufferCQEHandler<Br>(buffers));
84template <
typename MultiShotFunc, BufferRingLike Br,
typename Func,
86auto make_multishot_select_buffer_op_awaiter(MultiShotFunc &&multishot_func,
87 Br *buffers, Func &&func,
89 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
91 unwrap_fixed(std::forward<Args>(args))](Ring *ring) {
92 auto *sqe = ring->get_sqe();
94 sqe->flags |= IOSQE_BUFFER_SELECT;
95 sqe->buf_group = bgid;
99 std::move(prep_func), SelectBufferCQEHandler<Br>(buffers),
100 std::forward<MultiShotFunc>(multishot_func));
103#if CONDY_URING_VERSION_GE(2, 7)
104template <BufferRingLike Br,
typename Func,
typename... Args>
105auto make_bundle_select_buffer_op_awaiter(Br *buffers, Func &&func,
107 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
109 unwrap_fixed(std::forward<Args>(args))](Ring *ring) {
110 auto *sqe = ring->get_sqe();
112 sqe->flags |= IOSQE_BUFFER_SELECT;
113 sqe->buf_group = bgid;
114 sqe->ioprio |= IORING_RECVSEND_BUNDLE;
118 SelectBufferCQEHandler<Br>(buffers));
122#if CONDY_URING_VERSION_GE(2, 7)
123template <
typename MultiShotFunc, BufferRingLike Br,
typename Func,
125auto make_multishot_bundle_select_buffer_op_awaiter(
126 MultiShotFunc &&multishot_func, Br *buffers, Func &&func, Args &&...args) {
127 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
129 unwrap_fixed(std::forward<Args>(args))](Ring *ring) {
130 auto *sqe = ring->get_sqe();
132 sqe->flags |= IOSQE_BUFFER_SELECT;
133 sqe->buf_group = bgid;
134 sqe->ioprio |= IORING_RECVSEND_BUNDLE;
138 std::move(prep_func), SelectBufferCQEHandler<Br>(buffers),
139 std::forward<MultiShotFunc>(multishot_func));
143template <
typename FreeFunc,
typename Func,
typename... Args>
144auto make_zero_copy_op_awaiter(FreeFunc &&free_func, Func &&func,
146 auto prep_func = [func = std::forward<Func>(func),
148 unwrap_fixed(std::forward<Args>(args))](Ring *ring) {
149 auto *sqe = ring->get_sqe();
154 std::forward<FreeFunc>(free_func));
157template <
typename Awaiter>
158auto maybe_flag_fixed_fd(Awaiter &&op,
const FixedFd &) {
162template <
typename Awaiter>
auto maybe_flag_fixed_fd(Awaiter &&op,
int) {
163 return std::forward<Awaiter>(op);
166template <
typename Fd>
167constexpr bool is_fixed_fd_v = std::is_same_v<std::remove_cvref_t<Fd>, FixedFd>;
169inline void prep_send_fixed(io_uring_sqe *sqe,
int sockfd,
const void *buf,
170 size_t len,
int flags,
int buf_index)
noexcept {
171 io_uring_prep_send(sqe, sockfd, buf, len, flags);
172 sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
173 sqe->buf_index = buf_index;
176inline void prep_recv_fixed(io_uring_sqe *sqe,
int sockfd,
void *buf,
177 size_t len,
int flags,
int buf_index)
noexcept {
178 io_uring_prep_recv(sqe, sockfd, buf, len, flags);
179 sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
180 sqe->buf_index = buf_index;
183inline void prep_sendto(io_uring_sqe *sqe,
int sockfd,
const void *buf,
184 size_t len,
int flags,
const struct sockaddr *addr,
185 socklen_t addrlen)
noexcept {
186 io_uring_prep_send(sqe, sockfd, buf, len, flags);
187 io_uring_prep_send_set_addr(sqe, addr, addrlen);
190inline void prep_sendto_fixed(io_uring_sqe *sqe,
int sockfd,
const void *buf,
191 size_t len,
int flags,
192 const struct sockaddr *addr, socklen_t addrlen,
193 int buf_index)
noexcept {
194 prep_sendto(sqe, sockfd, buf, len, flags, addr, addrlen);
195 sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
196 sqe->buf_index = buf_index;
199inline void prep_sendto_zc(io_uring_sqe *sqe,
int sockfd,
const void *buf,
200 size_t len,
int flags,
const struct sockaddr *addr,
201 socklen_t addrlen,
unsigned zc_flags)
noexcept {
202 io_uring_prep_send_zc(sqe, sockfd, buf, len, flags, zc_flags);
203 io_uring_prep_send_set_addr(sqe, addr, addrlen);
206inline void prep_sendto_zc_fixed(io_uring_sqe *sqe,
int sockfd,
const void *buf,
207 size_t len,
int flags,
208 const struct sockaddr *addr, socklen_t addrlen,
209 unsigned zc_flags,
int buf_index)
noexcept {
210 prep_sendto_zc(sqe, sockfd, buf, len, flags, addr, addrlen, zc_flags);
211 sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
212 sqe->buf_index = buf_index;
215#if CONDY_URING_VERSION_GE(2, 15)
216inline void prep_recv_zc_multishot(io_uring_sqe *sqe,
int fd,
218 io_uring_prep_rw(IORING_OP_RECV_ZC, sqe, fd,
nullptr, 0, 0);
219 sqe->ioprio |= IORING_RECV_MULTISHOT;
220 sqe->zcrx_ifq_idx = zcrx_id;
224inline void prep_read(io_uring_sqe *sqe,
int fd,
void *buf,
unsigned nbytes,
225 __u64 offset,
int flags)
noexcept {
226 io_uring_prep_read(sqe, fd, buf, nbytes, offset);
227 sqe->rw_flags = flags;
230inline void prep_read_fixed(io_uring_sqe *sqe,
int fd,
void *buf,
231 unsigned nbytes, __u64 offset,
int flags,
232 int buf_index)
noexcept {
233 io_uring_prep_read_fixed(sqe, fd, buf, nbytes, offset, buf_index);
234 sqe->rw_flags = flags;
237inline void prep_write(io_uring_sqe *sqe,
int fd,
const void *buf,
238 unsigned nbytes, __u64 offset,
int flags)
noexcept {
239 io_uring_prep_write(sqe, fd, buf, nbytes, offset);
240 sqe->rw_flags = flags;
243inline void prep_write_fixed(io_uring_sqe *sqe,
int fd,
const void *buf,
244 unsigned nbytes, __u64 offset,
int flags,
245 int buf_index)
noexcept {
246 io_uring_prep_write_fixed(sqe, fd, buf, nbytes, offset, buf_index);
247 sqe->rw_flags = flags;
Helper functions for composing asynchronous operations.
Definitions of CQE handlers.
Helper functions for asynchronous operations.
The main namespace for the Condy library.
auto build_zero_copy_op_awaiter(PrepFunc &&func, CQEHandler &&cqe_handler, FreeFunc &&free_func)
Build a zero-copy operation awaiter with custom CQE handler.
auto build_op_awaiter(PrepFunc &&func, CQEHandler &&cqe_handler)
Build a single-shot operation awaiter with custom CQE handler.
auto build_multishot_op_awaiter(PrepFunc &&func, CQEHandler &&cqe_handler, MultiShotFunc &&multishot_func)
Build a multi-shot operation awaiter with custom CQE handler.
auto flag(Sender &&sender)
Decorates an operation with specific io_uring sqe flags.