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();
107template <
typename MultiShotFunc,
typename Func,
typename... Args>
108auto make_multishot_op_awaiter(MultiShotFunc &&multishot_func, Func &&func,
110 auto prep_func = [func = std::forward<Func>(func),
111 ... args = std::forward<Args>(args)](Ring *ring) {
112 auto *sqe = ring->get_sqe();
117 std::move(prep_func), std::forward<MultiShotFunc>(multishot_func));
120template <BufferRingLike Br,
typename Func,
typename... Args>
121auto make_select_buffer_op_awaiter(Br *buffers, Func &&func, Args &&...args) {
122 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
123 ... args = std::forward<Args>(args)](Ring *ring) {
124 auto *sqe = ring->get_sqe();
126 sqe->flags |= IOSQE_BUFFER_SELECT;
127 sqe->buf_group = bgid;
134template <
typename MultiShotFunc, BufferRingLike Br,
typename Func,
136auto make_multishot_select_buffer_op_awaiter(MultiShotFunc &&multishot_func,
137 Br *buffers, Func &&func,
139 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
140 ... args = std::forward<Args>(args)](Ring *ring) {
141 auto *sqe = ring->get_sqe();
143 sqe->flags |= IOSQE_BUFFER_SELECT;
144 sqe->buf_group = bgid;
148 std::move(prep_func), std::forward<MultiShotFunc>(multishot_func),
152#if !IO_URING_CHECK_VERSION(2, 7)
153template <BufferRingLike Br,
typename Func,
typename... Args>
154auto make_bundle_select_buffer_op_awaiter(Br *buffers, Func &&func,
156 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
157 ... args = std::forward<Args>(args)](Ring *ring) {
158 auto *sqe = ring->get_sqe();
160 sqe->flags |= IOSQE_BUFFER_SELECT;
161 sqe->buf_group = bgid;
162 sqe->ioprio |= IORING_RECVSEND_BUNDLE;
170#if !IO_URING_CHECK_VERSION(2, 7)
171template <
typename MultiShotFunc, BufferRingLike Br,
typename Func,
173auto make_multishot_bundle_select_buffer_op_awaiter(
174 MultiShotFunc &&multishot_func, Br *buffers, Func &&func, Args &&...args) {
175 auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
176 ... args = std::forward<Args>(args)](Ring *ring) {
177 auto *sqe = ring->get_sqe();
179 sqe->flags |= IOSQE_BUFFER_SELECT;
180 sqe->buf_group = bgid;
181 sqe->ioprio |= IORING_RECVSEND_BUNDLE;
185 std::move(prep_func), std::forward<MultiShotFunc>(multishot_func),
190template <
typename FreeFunc,
typename Func,
typename... Args>
191auto make_zero_copy_op_awaiter(FreeFunc &&free_func, Func &&func,
193 auto prep_func = [func = std::forward<Func>(func),
194 ... args = std::forward<Args>(args)](Ring *ring) {
195 auto *sqe = ring->get_sqe();
200 std::move(prep_func), std::forward<FreeFunc>(free_func));
211template <
unsigned int Flags, AwaiterLike Awaiter>
213 return FlaggedOpAwaiter<Flags, std::decay_t<Awaiter>>(
214 std::forward<Awaiter>(awaiter));
221template <AwaiterLike Awaiter>
auto drain(Awaiter &&awaiter) {
241template <
template <AwaiterLike... Awaiter>
typename AwaiterType,
242 AwaiterLike... Awaiter>
244 return AwaiterType<std::decay_t<Awaiter>...>(
245 std::forward<Awaiter>(awaiters)...);
256template <
template <
typename Awaiter>
typename RangedAwaiterType,
259 using AwaiterType =
typename std::decay_t<Range>::value_type;
260 auto begin = std::make_move_iterator(std::begin(range));
261 auto end = std::make_move_iterator(std::end(range));
262 std::vector<AwaiterType> awaiters(begin, end);
263 return RangedAwaiterType<AwaiterType>(std::move(awaiters));
273template <AwaiterLike... Awaiters>
auto when_all(Awaiters &&...awaiters) {
284template <AwaiterRange Range>
auto when_all(Range &&range) {
297template <AwaiterLike... Awaiters>
auto when_any(Awaiters &&...awaiters) {
308template <AwaiterRange Range>
auto when_any(Range &&range) {
319template <AwaiterLike... Awaiters>
auto link(Awaiters &&...awaiters) {
330template <AwaiterRange Range>
auto link(Range &&range) {
341template <AwaiterLike... Awaiters>
auto hard_link(Awaiters &&...awaiters) {
352template <AwaiterRange Range>
auto hard_link(Range &&range) {
364template <AwaiterLike Awaiter1, AwaiterLike Awaiter2>
366 return when_all(std::move(aw1), std::move(aw2));
372template <AwaiterLike Awaiter, AwaiterLike... Awaiters>
374 return WhenAllAwaiter<Awaiters..., std::decay_t<Awaiter>>(std::move(aws),
381template <AwaiterLike Awaiter1, AwaiterLike Awaiter2>
383 return when_any(std::move(aw1), std::move(aw2));
389template <AwaiterLike Awaiter, AwaiterLike... Awaiters>
391 return WhenAnyAwaiter<Awaiters..., std::decay_t<Awaiter>>(std::move(aws),
398template <AwaiterLike Awaiter1, AwaiterLike Awaiter2>
400 return link(std::move(aw1), std::move(aw2));
406template <AwaiterLike Awaiter, AwaiterLike... Awaiters>
408 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.