Condy v1.8
C++ Asynchronous System Call Layer for Linux
Loading...
Searching...
No Matches
async_operations.hpp
Go to the documentation of this file.
1
8
9#pragma once
10
12#include "condy/concepts.hpp"
13#include "condy/condy_uring.hpp"
14#include "condy/cqe_handler.hpp"
16
17namespace condy {
18namespace detail {
19
20template <typename Func, typename... Args>
21auto make_op_awaiter(Func &&func, Args &&...args) {
22 auto prep_func = [func = std::forward<Func>(func),
23 ... args = std::forward<Args>(args)](Ring *ring) {
24 auto *sqe = ring->get_sqe();
25 func(sqe, args...);
26 return sqe;
27 };
28 return build_op_awaiter<SimpleCQEHandler>(std::move(prep_func));
29}
30
31#if !IO_URING_CHECK_VERSION(2, 13) // >= 2.13
32template <typename Func, typename... Args>
33auto make_op_awaiter128(Func &&func, Args &&...args) {
34 auto prep_func = [func = std::forward<Func>(func),
35 ... args = std::forward<Args>(args)](Ring *ring) {
36 auto *sqe = ring->get_sqe128();
37 if (!sqe) {
38 panic_on("SQE128 not enabled in the ring");
39 }
40 func(sqe, args...);
41 return sqe;
42 };
43 return build_op_awaiter<SimpleCQEHandler>(std::move(prep_func));
44}
45#endif
46
47template <typename MultiShotFunc, typename Func, typename... Args>
48auto make_multishot_op_awaiter(MultiShotFunc &&multishot_func, Func &&func,
49 Args &&...args) {
50 auto prep_func = [func = std::forward<Func>(func),
51 ... args = std::forward<Args>(args)](Ring *ring) {
52 auto *sqe = ring->get_sqe();
53 func(sqe, args...);
54 return sqe;
55 };
57 std::move(prep_func), std::forward<MultiShotFunc>(multishot_func));
58}
59
60template <BufferRingLike Br, typename Func, typename... Args>
61auto make_select_buffer_op_awaiter(Br *buffers, Func &&func, Args &&...args) {
62 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
63 ... args = std::forward<Args>(args)](Ring *ring) {
64 auto *sqe = ring->get_sqe();
65 func(sqe, args...);
66 sqe->flags |= IOSQE_BUFFER_SELECT;
67 sqe->buf_group = bgid;
68 return sqe;
69 };
70 return build_op_awaiter<SelectBufferCQEHandler<Br>>(std::move(prep_func),
71 buffers);
72}
73
74template <typename MultiShotFunc, BufferRingLike Br, typename Func,
75 typename... Args>
76auto make_multishot_select_buffer_op_awaiter(MultiShotFunc &&multishot_func,
77 Br *buffers, Func &&func,
78 Args &&...args) {
79 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
80 ... args = std::forward<Args>(args)](Ring *ring) {
81 auto *sqe = ring->get_sqe();
82 func(sqe, args...);
83 sqe->flags |= IOSQE_BUFFER_SELECT;
84 sqe->buf_group = bgid;
85 return sqe;
86 };
88 std::move(prep_func), std::forward<MultiShotFunc>(multishot_func),
89 buffers);
90}
91
92#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
93template <BufferRingLike Br, typename Func, typename... Args>
94auto make_bundle_select_buffer_op_awaiter(Br *buffers, Func &&func,
95 Args &&...args) {
96 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
97 ... args = std::forward<Args>(args)](Ring *ring) {
98 auto *sqe = ring->get_sqe();
99 func(sqe, args...);
100 sqe->flags |= IOSQE_BUFFER_SELECT;
101 sqe->buf_group = bgid;
102 sqe->ioprio |= IORING_RECVSEND_BUNDLE;
103 return sqe;
104 };
105 return build_op_awaiter<SelectBufferCQEHandler<Br>>(std::move(prep_func),
106 buffers);
107}
108#endif
109
110#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
111template <typename MultiShotFunc, BufferRingLike Br, typename Func,
112 typename... Args>
113auto make_multishot_bundle_select_buffer_op_awaiter(
114 MultiShotFunc &&multishot_func, Br *buffers, Func &&func, Args &&...args) {
115 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
116 ... args = std::forward<Args>(args)](Ring *ring) {
117 auto *sqe = ring->get_sqe();
118 func(sqe, args...);
119 sqe->flags |= IOSQE_BUFFER_SELECT;
120 sqe->buf_group = bgid;
121 sqe->ioprio |= IORING_RECVSEND_BUNDLE;
122 return sqe;
123 };
125 std::move(prep_func), std::forward<MultiShotFunc>(multishot_func),
126 buffers);
127}
128#endif
129
130template <typename FreeFunc, typename Func, typename... Args>
131auto make_zero_copy_op_awaiter(FreeFunc &&free_func, Func &&func,
132 Args &&...args) {
133 auto prep_func = [func = std::forward<Func>(func),
134 ... args = std::forward<Args>(args)](Ring *ring) {
135 auto *sqe = ring->get_sqe();
136 func(sqe, args...);
137 return sqe;
138 };
140 std::move(prep_func), std::forward<FreeFunc>(free_func));
141}
142
143template <typename Awaiter>
144auto maybe_flag_fixed_fd(Awaiter &&op, const FixedFd &) {
145 return flag<IOSQE_FIXED_FILE>(std::forward<Awaiter>(op));
146}
147
148template <typename Awaiter> auto maybe_flag_fixed_fd(Awaiter &&op, int) {
149 return std::forward<Awaiter>(op);
150}
151
152template <typename Fd>
153constexpr bool is_fixed_fd_v = std::is_same_v<std::remove_cvref_t<Fd>, FixedFd>;
154
155inline void prep_sendto(io_uring_sqe *sqe, int sockfd, const void *buf,
156 size_t len, int flags, const struct sockaddr *addr,
157 socklen_t addrlen) noexcept {
158 io_uring_prep_send(sqe, sockfd, buf, len, flags);
159 io_uring_prep_send_set_addr(sqe, addr, addrlen);
160}
161
162inline void prep_send_fixed(io_uring_sqe *sqe, int sockfd, const void *buf,
163 size_t len, int flags, int buf_index) noexcept {
164 io_uring_prep_send(sqe, sockfd, buf, len, flags);
165 sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
166 sqe->buf_index = buf_index;
167}
168
169inline void prep_sendto_fixed(io_uring_sqe *sqe, int sockfd, const void *buf,
170 size_t len, int flags,
171 const struct sockaddr *addr, socklen_t addrlen,
172 int buf_index) noexcept {
173 prep_sendto(sqe, sockfd, buf, len, flags, addr, addrlen);
174 sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
175 sqe->buf_index = buf_index;
176}
177
178inline void prep_sendto_zc(io_uring_sqe *sqe, int sockfd, const void *buf,
179 size_t len, int flags, const struct sockaddr *addr,
180 socklen_t addrlen, unsigned zc_flags) noexcept {
181 io_uring_prep_send_zc(sqe, sockfd, buf, len, flags, zc_flags);
182 io_uring_prep_send_set_addr(sqe, addr, addrlen);
183}
184
185inline void prep_sendto_zc_fixed(io_uring_sqe *sqe, int sockfd, const void *buf,
186 size_t len, int flags,
187 const struct sockaddr *addr, socklen_t addrlen,
188 unsigned zc_flags, int buf_index) noexcept {
189 prep_sendto_zc(sqe, sockfd, buf, len, flags, addr, addrlen, zc_flags);
190 sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
191 sqe->buf_index = buf_index;
192}
193
194#if !IO_URING_CHECK_VERSION(2, 15) // >= 2.15
195inline void prep_recv_zc_multishot(io_uring_sqe *sqe, int fd,
196 uint32_t zcrx_id) {
197 io_uring_prep_rw(IORING_OP_RECV_ZC, sqe, fd, nullptr, 0, 0);
198 sqe->ioprio |= IORING_RECV_MULTISHOT;
199 sqe->zcrx_ifq_idx = zcrx_id;
200}
201#endif
202
203} // namespace detail
204} // namespace condy
Helper functions for composing asynchronous operations.
Definitions of CQE handlers.
Helper functions for asynchronous operations.
The main namespace for the Condy library.
Definition condy.hpp:37
auto build_op_awaiter(PrepFunc &&func, Args &&...handler_args)
Build a single-shot operation awaiter with custom CQE handler.
auto build_zero_copy_op_awaiter(PrepFunc &&func, FreeFunc &&free_func, Args &&...handler_args)
Build a zero-copy operation awaiter with custom CQE handler.
auto build_multishot_op_awaiter(PrepFunc &&func, MultiShotFunc &&multishot_func, Args &&...handler_args)
Build a multi-shot operation awaiter with custom CQE handler.
auto flag(Sender &&sender)
Decorates an operation with specific io_uring sqe flags.