29template <CQEHandlerLike CQEHandler, PrepFuncLike PrepFunc,
typename... Args>
31 return OpAwaiter<std::decay_t<PrepFunc>, CQEHandler>(
32 std::forward<PrepFunc>(func), std::forward<Args>(handler_args)...);
48template <CQEHandlerLike CQEHandler, PrepFuncLike PrepFunc,
49 typename MultiShotFunc,
typename... Args>
51 Args &&...handler_args) {
52 return MultiShotOpAwaiter<std::decay_t<PrepFunc>, CQEHandler,
53 std::decay_t<MultiShotFunc>>(
54 std::forward<PrepFunc>(func),
55 std::forward<MultiShotFunc>(multishot_func),
56 std::forward<Args>(handler_args)...);
71template <CQEHandlerLike CQEHandler, PrepFuncLike PrepFunc,
typename FreeFunc,
74 Args &&...handler_args) {
75 return ZeroCopyOpAwaiter<std::decay_t<PrepFunc>, CQEHandler,
76 std::decay_t<FreeFunc>>(
77 std::forward<PrepFunc>(func), std::forward<FreeFunc>(free_func),
78 std::forward<Args>(handler_args)...);
83template <
typename Func,
typename... Args>
84auto make_op_awaiter(Func &&func, Args &&...args) {
85 auto prep_func = [func = std::forward<Func>(func),
86 ... args = std::forward<Args>(args)](Ring *ring) {
87 auto *sqe = ring->get_sqe();
94#if !IO_URING_CHECK_VERSION(2, 13)
95template <
typename Func,
typename... Args>
96auto make_op_awaiter128(Func &&func, Args &&...args) {
97 auto prep_func = [func = std::forward<Func>(func),
98 ... args = std::forward<Args>(args)](Ring *ring) {
99 auto *sqe = ring->get_sqe128();
101 panic_on(
"SQE128 not enabled in the ring");
110template <
typename MultiShotFunc,
typename Func,
typename... Args>
111auto make_multishot_op_awaiter(MultiShotFunc &&multishot_func, Func &&func,
113 auto prep_func = [func = std::forward<Func>(func),
114 ... args = std::forward<Args>(args)](Ring *ring) {
115 auto *sqe = ring->get_sqe();
120 std::move(prep_func), std::forward<MultiShotFunc>(multishot_func));
123template <BufferRingLike Br,
typename Func,
typename... Args>
124auto make_select_buffer_op_awaiter(Br *buffers, Func &&func, Args &&...args) {
125 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
126 ... args = std::forward<Args>(args)](Ring *ring) {
127 auto *sqe = ring->get_sqe();
129 sqe->flags |= IOSQE_BUFFER_SELECT;
130 sqe->buf_group = bgid;
137template <
typename MultiShotFunc, BufferRingLike Br,
typename Func,
139auto make_multishot_select_buffer_op_awaiter(MultiShotFunc &&multishot_func,
140 Br *buffers, Func &&func,
142 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
143 ... args = std::forward<Args>(args)](Ring *ring) {
144 auto *sqe = ring->get_sqe();
146 sqe->flags |= IOSQE_BUFFER_SELECT;
147 sqe->buf_group = bgid;
151 std::move(prep_func), std::forward<MultiShotFunc>(multishot_func),
155#if !IO_URING_CHECK_VERSION(2, 7)
156template <BufferRingLike Br,
typename Func,
typename... Args>
157auto make_bundle_select_buffer_op_awaiter(Br *buffers, Func &&func,
159 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
160 ... args = std::forward<Args>(args)](Ring *ring) {
161 auto *sqe = ring->get_sqe();
163 sqe->flags |= IOSQE_BUFFER_SELECT;
164 sqe->buf_group = bgid;
165 sqe->ioprio |= IORING_RECVSEND_BUNDLE;
173#if !IO_URING_CHECK_VERSION(2, 7)
174template <
typename MultiShotFunc, BufferRingLike Br,
typename Func,
176auto make_multishot_bundle_select_buffer_op_awaiter(
177 MultiShotFunc &&multishot_func, Br *buffers, Func &&func, Args &&...args) {
178 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
179 ... args = std::forward<Args>(args)](Ring *ring) {
180 auto *sqe = ring->get_sqe();
182 sqe->flags |= IOSQE_BUFFER_SELECT;
183 sqe->buf_group = bgid;
184 sqe->ioprio |= IORING_RECVSEND_BUNDLE;
188 std::move(prep_func), std::forward<MultiShotFunc>(multishot_func),
193template <
typename FreeFunc,
typename Func,
typename... Args>
194auto make_zero_copy_op_awaiter(FreeFunc &&free_func, Func &&func,
196 auto prep_func = [func = std::forward<Func>(func),
197 ... args = std::forward<Args>(args)](Ring *ring) {
198 auto *sqe = ring->get_sqe();
203 std::move(prep_func), std::forward<FreeFunc>(free_func));
214template <
unsigned int Flags, AwaiterLike Awaiter>
216 return FlaggedOpAwaiter<Flags, std::decay_t<Awaiter>>(
217 std::forward<Awaiter>(awaiter));
224template <AwaiterLike Awaiter>
auto drain(Awaiter &&awaiter) {
244template <
template <AwaiterLike... Awaiter>
typename AwaiterType,
245 AwaiterLike... Awaiter>
247 return AwaiterType<std::decay_t<Awaiter>...>(
248 std::forward<Awaiter>(awaiters)...);
259template <
template <
typename Awaiter>
typename RangedAwaiterType,
262 using AwaiterType =
typename std::decay_t<Range>::value_type;
263 auto begin = std::make_move_iterator(std::begin(range));
264 auto end = std::make_move_iterator(std::end(range));
265 std::vector<AwaiterType> awaiters(begin, end);
266 return RangedAwaiterType<AwaiterType>(std::move(awaiters));
276template <AwaiterLike... Awaiters>
auto when_all(Awaiters &&...awaiters) {
287template <AwaiterRange Range>
auto when_all(Range &&range) {
300template <AwaiterLike... Awaiters>
auto when_any(Awaiters &&...awaiters) {
311template <AwaiterRange Range>
auto when_any(Range &&range) {
322template <AwaiterLike... Awaiters>
auto link(Awaiters &&...awaiters) {
333template <AwaiterRange Range>
auto link(Range &&range) {
344template <AwaiterLike... Awaiters>
auto hard_link(Awaiters &&...awaiters) {
355template <AwaiterRange Range>
auto hard_link(Range &&range) {
367template <AwaiterLike Awaiter1, AwaiterLike Awaiter2>
369 return when_all(std::move(aw1), std::move(aw2));
375template <AwaiterLike Awaiter, AwaiterLike... Awaiters>
377 return WhenAllAwaiter<Awaiters..., std::decay_t<Awaiter>>(std::move(aws),
384template <AwaiterLike Awaiter1, AwaiterLike Awaiter2>
386 return when_any(std::move(aw1), std::move(aw2));
392template <AwaiterLike Awaiter, AwaiterLike... Awaiters>
394 return WhenAnyAwaiter<Awaiters..., std::decay_t<Awaiter>>(std::move(aws),
401template <AwaiterLike Awaiter1, AwaiterLike Awaiter2>
403 return link(std::move(aw1), std::move(aw2));
409template <AwaiterLike Awaiter, AwaiterLike... Awaiters>
411 return LinkAwaiter<Awaiters..., std::decay_t<Awaiter>>(std::move(aws),
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.
auto parallel(Awaiter &&...awaiters)
Compose multiple awaiters into a single awaiter that executes them in parallel.
auto build_op_awaiter(PrepFunc &&func, Args &&...handler_args)
Build a single-shot operation awaiter with custom CQE handler.
auto drain(Awaiter &&awaiter)
Mark an awaiter as drain operation.
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 when_all(Awaiters &&...awaiters)
Compose multiple awaiters into a single awaiter that completes when all of them complete.
auto link(Awaiters &&...awaiters)
Compose multiple awaiters into a single awaiter that executes them in sequence.
LinkAwaiterBase< IOSQE_IO_LINK, Awaiter... > LinkAwaiter
Awaiter that links multiple operations using IO_LINK.
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.
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.
auto always_async(Awaiter &&awaiter)
Mark an awaiter to always execute asynchronously.
Wrapper classes for liburing interfaces.