Condy v1.3.0
C++ Asynchronous System Call Layer for Linux
Loading...
Searching...
No Matches
awaiter_operations.hpp
Go to the documentation of this file.
1
9
10#pragma once
11
12#include "condy/awaiters.hpp"
13#include "condy/concepts.hpp"
14#include "condy/cqe_handler.hpp"
15#include "condy/ring.hpp"
16
17namespace condy {
18
24template <typename Func, typename... Args>
25auto make_op_awaiter(Func &&func, Args &&...args) {
26 auto prep_func = [func = std::forward<Func>(func),
27 ... args = std::forward<Args>(args)](Ring *ring) {
28 auto *sqe = ring->get_sqe();
29 func(sqe, args...);
30 return sqe;
31 };
32 return OpAwaiter<decltype(prep_func), SimpleCQEHandler>(
33 std::move(prep_func));
34}
35
36#if !IO_URING_CHECK_VERSION(2, 13) // >= 2.13
40template <typename Func, typename... Args>
41auto make_op_awaiter128(Func &&func, Args &&...args) {
42 auto prep_func = [func = std::forward<Func>(func),
43 ... args = std::forward<Args>(args)](Ring *ring) {
44 auto *sqe = ring->get_sqe128();
45 func(sqe, args...);
46 return sqe;
47 };
48 return OpAwaiter<decltype(prep_func), SimpleCQEHandler>(
49 std::move(prep_func));
50}
51#endif
52
56template <typename MultiShotFunc, typename Func, typename... Args>
57auto make_multishot_op_awaiter(MultiShotFunc &&multishot_func, Func &&func,
58 Args &&...args) {
59 auto prep_func = [func = std::forward<Func>(func),
60 ... args = std::forward<Args>(args)](Ring *ring) {
61 auto *sqe = ring->get_sqe();
62 func(sqe, args...);
63 return sqe;
64 };
65 return MultiShotOpAwaiter<decltype(prep_func), SimpleCQEHandler,
66 std::decay_t<MultiShotFunc>>(
67 std::move(prep_func), std::forward<MultiShotFunc>(multishot_func));
68}
69
73template <BufferRingLike Br, typename Func, typename... Args>
74auto make_select_buffer_op_awaiter(Br *buffers, Func &&func, Args &&...args) {
75 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
76 ... args = std::forward<Args>(args)](Ring *ring) {
77 auto *sqe = ring->get_sqe();
78 func(sqe, args...);
79 sqe->flags |= IOSQE_BUFFER_SELECT;
80 sqe->buf_group = bgid;
81 return sqe;
82 };
83 return OpAwaiter<decltype(prep_func), SelectBufferCQEHandler<Br>>(
84 std::move(prep_func), buffers);
85}
86
90template <typename MultiShotFunc, BufferRingLike Br, typename Func,
91 typename... Args>
92auto make_multishot_select_buffer_op_awaiter(MultiShotFunc &&multishot_func,
93 Br *buffers, Func &&func,
94 Args &&...args) {
95 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
96 ... args = std::forward<Args>(args)](Ring *ring) {
97 auto *sqe = ring->get_sqe();
98 func(sqe, args...);
99 sqe->flags |= IOSQE_BUFFER_SELECT;
100 sqe->buf_group = bgid;
101 return sqe;
102 };
103 return MultiShotOpAwaiter<decltype(prep_func), SelectBufferCQEHandler<Br>,
104 std::decay_t<MultiShotFunc>>(
105 std::move(prep_func), std::forward<MultiShotFunc>(multishot_func),
106 buffers);
107}
108
109#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
113template <BufferRingLike Br, typename Func, typename... Args>
114auto make_bundle_select_buffer_op_awaiter(Br *buffers, Func &&func,
115 Args &&...args) {
116 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
117 ... args = std::forward<Args>(args)](Ring *ring) {
118 auto *sqe = ring->get_sqe();
119 func(sqe, args...);
120 sqe->flags |= IOSQE_BUFFER_SELECT;
121 sqe->buf_group = bgid;
122 sqe->ioprio |= IORING_RECVSEND_BUNDLE;
123 return sqe;
124 };
125 return OpAwaiter<decltype(prep_func), SelectBufferCQEHandler<Br>>(
126 std::move(prep_func), buffers);
127}
128#endif
129
130#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
134template <typename MultiShotFunc, BufferRingLike Br, typename Func,
135 typename... Args>
137 MultiShotFunc &&multishot_func, Br *buffers, Func &&func, Args &&...args) {
138 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
139 ... args = std::forward<Args>(args)](Ring *ring) {
140 auto *sqe = ring->get_sqe();
141 func(sqe, args...);
142 sqe->flags |= IOSQE_BUFFER_SELECT;
143 sqe->buf_group = bgid;
144 sqe->ioprio |= IORING_RECVSEND_BUNDLE;
145 return sqe;
146 };
147 return MultiShotOpAwaiter<decltype(prep_func), SelectBufferCQEHandler<Br>,
148 std::decay_t<MultiShotFunc>>(
149 std::move(prep_func), std::forward<MultiShotFunc>(multishot_func),
150 buffers);
151}
152#endif
153
157template <typename FreeFunc, typename Func, typename... Args>
158auto make_zero_copy_op_awaiter(FreeFunc &&free_func, Func &&func,
159 Args &&...args) {
160 auto prep_func = [func = std::forward<Func>(func),
161 ... args = std::forward<Args>(args)](Ring *ring) {
162 auto *sqe = ring->get_sqe();
163 func(sqe, args...);
164 return sqe;
165 };
166 return ZeroCopyOpAwaiter<decltype(prep_func), SimpleCQEHandler,
167 std::decay_t<FreeFunc>>(
168 std::move(prep_func), std::forward<FreeFunc>(free_func));
169}
170
177template <unsigned int Flags, AwaiterLike Awaiter>
178auto flag(Awaiter &&awaiter) {
179 return FlaggedOpAwaiter<Flags, std::decay_t<Awaiter>>(
180 std::forward<Awaiter>(awaiter));
181}
182
187template <AwaiterLike Awaiter> auto drain(Awaiter &&awaiter) {
188 return flag<IOSQE_IO_DRAIN>(std::forward<Awaiter>(awaiter));
189}
190
195template <AwaiterLike Awaiter> auto always_async(Awaiter &&awaiter) {
196 return flag<IOSQE_ASYNC>(std::forward<Awaiter>(awaiter));
197}
198
207template <template <AwaiterLike... Awaiter> typename AwaiterType,
208 AwaiterLike... Awaiter>
209auto parallel(Awaiter &&...awaiters) {
210 return AwaiterType<std::decay_t<Awaiter>...>(
211 std::forward<Awaiter>(awaiters)...);
212}
213
222template <template <typename Awaiter> typename RangedAwaiterType,
223 AwaiterRange Range>
224auto parallel(Range &&range) {
225 using AwaiterType = typename std::decay_t<Range>::value_type;
226 auto begin = std::make_move_iterator(std::begin(range));
227 auto end = std::make_move_iterator(std::end(range));
228 std::vector<AwaiterType> awaiters(begin, end);
229 return RangedAwaiterType<AwaiterType>(std::move(awaiters));
230}
231
239template <AwaiterLike... Awaiters> auto when_all(Awaiters &&...awaiters) {
240 return parallel<WhenAllAwaiter>(std::forward<Awaiters>(awaiters)...);
241}
242
250template <AwaiterRange Range> auto when_all(Range &&range) {
251 return parallel<RangedWhenAllAwaiter>(std::forward<Range>(range));
252}
253
263template <AwaiterLike... Awaiters> auto when_any(Awaiters &&...awaiters) {
264 return parallel<WhenAnyAwaiter>(std::forward<Awaiters>(awaiters)...);
265}
266
274template <AwaiterRange Range> auto when_any(Range &&range) {
275 return parallel<RangedWhenAnyAwaiter>(std::forward<Range>(range));
276}
277
285template <AwaiterLike... Awaiters> auto link(Awaiters &&...awaiters) {
286 return parallel<LinkAwaiter>(std::forward<Awaiters>(awaiters)...);
287}
288
296template <AwaiterRange Range> auto link(Range &&range) {
297 return parallel<RangedLinkAwaiter>(std::forward<Range>(range));
298}
299
307template <AwaiterLike... Awaiters> auto hard_link(Awaiters &&...awaiters) {
308 return parallel<HardLinkAwaiter>(std::forward<Awaiters>(awaiters)...);
309}
310
318template <AwaiterRange Range> auto hard_link(Range &&range) {
319 return parallel<RangedHardLinkAwaiter>(std::forward<Range>(range));
320}
321
325namespace operators {
326
330template <AwaiterLike Awaiter1, AwaiterLike Awaiter2>
331auto operator&&(Awaiter1 aw1, Awaiter2 aw2) {
332 return when_all(std::move(aw1), std::move(aw2));
333}
334
338template <AwaiterLike Awaiter, AwaiterLike... Awaiters>
340 return WhenAllAwaiter<Awaiters..., std::decay_t<Awaiter>>(std::move(aws),
341 std::move(aw));
342}
343
347template <AwaiterLike Awaiter1, AwaiterLike Awaiter2>
348auto operator||(Awaiter1 aw1, Awaiter2 aw2) {
349 return when_any(std::move(aw1), std::move(aw2));
350}
351
355template <AwaiterLike Awaiter, AwaiterLike... Awaiters>
357 return WhenAnyAwaiter<Awaiters..., std::decay_t<Awaiter>>(std::move(aws),
358 std::move(aw));
359}
360
364template <AwaiterLike Awaiter1, AwaiterLike Awaiter2>
365auto operator>>(Awaiter1 aw1, Awaiter2 aw2) {
366 return link(std::move(aw1), std::move(aw2));
367}
368
372template <AwaiterLike Awaiter, AwaiterLike... Awaiters>
374 return LinkAwaiter<Awaiters..., std::decay_t<Awaiter>>(std::move(aws),
375 std::move(aw));
376}
377
378} // namespace operators
379
380} // namespace condy
Definitions of awaiter types for asynchronous operations.
Definitions of CQE handlers.
Operators for composing awaiters.
auto operator||(Awaiter1 aw1, Awaiter2 aw2)
Operator overloads version of when_any.
auto operator&&(Awaiter1 aw1, Awaiter2 aw2)
Operator overloads version of when_all.
auto operator>>(Awaiter1 aw1, Awaiter2 aw2)
Operator overloads version of link.
The main namespace for the Condy library.
Definition condy.hpp:28
auto make_multishot_select_buffer_op_awaiter(MultiShotFunc &&multishot_func, Br *buffers, Func &&func, Args &&...args)
This function creates a variant of OpAwaiter. OpAwaiter represents an asynchronous operation that can...
auto make_op_awaiter(Func &&func, Args &&...args)
This function creates a variant of OpAwaiter. OpAwaiter represents an asynchronous operation that can...
auto parallel(Awaiter &&...awaiters)
Compose multiple awaiters into a single awaiter that executes them in parallel.
auto make_bundle_select_buffer_op_awaiter(Br *buffers, Func &&func, Args &&...args)
This function creates a variant of OpAwaiter. OpAwaiter represents an asynchronous operation that can...
auto drain(Awaiter &&awaiter)
Mark an awaiter as drain operation.
auto when_all(Awaiters &&...awaiters)
Compose multiple awaiters into a single awaiter that completes when all of them complete.
auto make_multishot_op_awaiter(MultiShotFunc &&multishot_func, Func &&func, Args &&...args)
This function creates a variant of OpAwaiter. OpAwaiter represents an asynchronous operation that can...
auto make_zero_copy_op_awaiter(FreeFunc &&free_func, Func &&func, Args &&...args)
This function creates a variant of OpAwaiter. OpAwaiter represents an asynchronous operation that can...
auto link(Awaiters &&...awaiters)
Compose multiple awaiters into a single awaiter that executes them in sequence.
auto make_op_awaiter128(Func &&func, Args &&...args)
This function creates a variant of OpAwaiter. OpAwaiter represents an asynchronous operation that can...
auto make_select_buffer_op_awaiter(Br *buffers, Func &&func, Args &&...args)
This function creates a variant of OpAwaiter. OpAwaiter represents an asynchronous operation that can...
LinkAwaiterBase< IOSQE_IO_LINK, Awaiter... > LinkAwaiter
Awaiter that links multiple operations using IO_LINK.
Definition awaiters.hpp:474
auto when_any(Awaiters &&...awaiters)
Compose multiple awaiters into a single awaiter that completes when any of them complete.
auto flag(Awaiter &&awaiter)
Decorates an awaiter with specific io_uring sqe flags.
ParallelAwaiterBase< WhenAllFinishHandle< typename Awaiter::HandleType... >, Awaiter... > WhenAllAwaiter
Awaiter that waits for all operations to complete in parallel.
Definition awaiters.hpp:420
auto hard_link(Awaiters &&...awaiters)
Compose multiple awaiters into a single awaiter that executes them in sequence and continues even if ...
ParallelAwaiterBase< WhenAnyFinishHandle< typename Awaiter::HandleType... >, Awaiter... > WhenAnyAwaiter
Awaiter that waits for any operation to complete in parallel.
Definition awaiters.hpp:432
auto make_multishot_bundle_select_buffer_op_awaiter(MultiShotFunc &&multishot_func, Br *buffers, Func &&func, Args &&...args)
This function creates a variant of OpAwaiter. OpAwaiter represents an asynchronous operation that can...
auto always_async(Awaiter &&awaiter)
Mark an awaiter to always execute asynchronously.
Wrapper classes for liburing interfaces.