Condy v1.8
C++ Asynchronous System Call Layer for Linux
Loading...
Searching...
No Matches
sender_operations.hpp
Go to the documentation of this file.
1
5
6#pragma once
7
8#include "condy/concepts.hpp"
9#include "condy/senders.hpp"
10#include <stdexcept>
11
12namespace condy {
13
14template <CQEHandlerLike CQEHandler, PrepFuncLike PrepFunc, typename... Args>
15auto build_op_sender(PrepFunc &&prep_func, Args &&...args) {
16 return OpSender<std::decay_t<PrepFunc>, CQEHandler>(
17 std::forward<PrepFunc>(prep_func),
18 CQEHandler(std::forward<Args>(args)...));
19}
20
21template <CQEHandlerLike CQEHandler, PrepFuncLike PrepFunc,
22 typename MultiShotFunc, typename... Args>
23auto build_multishot_op_sender(PrepFunc &&func, MultiShotFunc &&multishot_func,
24 Args &&...handler_args) {
25 return MultiShotOpSender<std::decay_t<PrepFunc>, CQEHandler,
26 std::decay_t<MultiShotFunc>>(
27 std::forward<PrepFunc>(func),
28 CQEHandler(std::forward<Args>(handler_args)...),
29 std::forward<MultiShotFunc>(multishot_func));
30}
31
32template <CQEHandlerLike CQEHandler, PrepFuncLike PrepFunc, typename FreeFunc,
33 typename... Args>
34auto build_zero_copy_op_sender(PrepFunc &&func, FreeFunc &&free_func,
35 Args &&...handler_args) {
36 return ZeroCopyOpSender<std::decay_t<PrepFunc>, CQEHandler,
37 std::decay_t<FreeFunc>>(
38 std::forward<PrepFunc>(func),
39 CQEHandler(std::forward<Args>(handler_args)...),
40 std::forward<FreeFunc>(free_func));
41}
42
48template <unsigned int Flags, typename Sender> auto flag(Sender &&sender) {
49 return detail::FlaggedOpSender<Flags, std::decay_t<Sender>>(
50 std::forward<Sender>(sender));
51}
52
57template <typename Sender> auto drain(Sender &&sender) {
58 return flag<IOSQE_IO_DRAIN>(std::forward<Sender>(sender));
59}
60
65template <typename Sender> auto always_async(Sender &&sender) {
66 return flag<IOSQE_ASYNC>(std::forward<Sender>(sender));
67}
68
75template <template <typename... Senders> typename SenderType,
76 typename... Senders>
77auto parallel(Senders &&...senders) {
78 return SenderType<std::decay_t<Senders>...>(
79 std::forward<Senders>(senders)...);
80}
81
88template <template <typename Sender> typename RangedSenderType,
89 std::ranges::range Range>
90auto parallel(Range &&range) {
91 using SenderType = typename std::remove_cvref_t<Range>::value_type;
92 auto begin = std::make_move_iterator(std::begin(range));
93 auto end = std::make_move_iterator(std::end(range));
94 std::vector<SenderType> senders(begin, end);
95 return RangedSenderType<SenderType>(std::move(senders));
96}
97
103template <typename... Senders> auto when_all(Senders &&...senders) {
104 return parallel<WhenAllSender>(std::forward<Senders>(senders)...);
105}
106
112template <std::ranges::range Range> auto when_all(Range &&range) {
113 return parallel<RangedWhenAllSender>(std::forward<Range>(range));
114}
115
121template <typename... Senders> auto when_any(Senders &&...senders) {
122 static_assert(sizeof...(Senders) > 0,
123 "when_any requires at least one sender");
124 return parallel<WhenAnySender>(std::forward<Senders>(senders)...);
125}
126
132template <std::ranges::range Range> auto when_any(Range &&range) {
133 if (std::ranges::empty(range)) {
134 throw std::invalid_argument("when_any requires at least one sender");
135 }
136 return parallel<RangedWhenAnySender>(std::forward<Range>(range));
137}
138
144template <typename... Senders> auto link(Senders &&...senders) {
145 return parallel<LinkSender>(std::forward<Senders>(senders)...);
146}
147
153template <std::ranges::range Range> auto link(Range &&range) {
154 return parallel<RangedLinkSender>(std::forward<Range>(range));
155}
156
162template <typename... Senders> auto hard_link(Senders &&...senders) {
163 return parallel<HardLinkSender>(std::forward<Senders>(senders)...);
164}
165
171template <std::ranges::range Range> auto hard_link(Range &&range) {
172 return parallel<RangedHardLinkSender>(std::forward<Range>(range));
173}
174
178namespace operators {
179
183template <typename Sender1, typename Sender2>
184auto operator&&(Sender1 s1, Sender2 s2) {
185 return when_all(std::move(s1), std::move(s2));
186}
187
191template <typename S, typename... Ss>
192auto operator&&(WhenAllSender<Ss...> aws, S sender) {
193 return WhenAllSender<Ss..., std::decay_t<S>>(std::move(aws),
194 std::move(sender));
195}
196
200template <typename Sender1, typename Sender2>
201auto operator||(Sender1 s1, Sender2 s2) {
202 return when_any(std::move(s1), std::move(s2));
203}
204
208template <typename S, typename... Ss>
209auto operator||(WhenAnySender<Ss...> aws, S sender) {
210 return WhenAnySender<Ss..., std::decay_t<S>>(std::move(aws),
211 std::move(sender));
212}
213
217template <typename Sender1, typename Sender2>
218auto operator>>(Sender1 s1, Sender2 s2) {
219 return link(std::move(s1), std::move(s2));
220}
221
225template <typename S, typename... Ss>
226auto operator>>(LinkSender<Ss...> aws, S sender) {
227 return LinkSender<Ss..., std::decay_t<S>>(std::move(aws),
228 std::move(sender));
229}
230
231} // namespace operators
232
233} // namespace condy
Operators for composing operations.
auto operator&&(Sender1 s1, Sender2 s2)
Operator overloads version of condy::when_all.
auto operator>>(Sender1 s1, Sender2 s2)
Operator overloads version of condy::link.
auto operator||(Sender1 s1, Sender2 s2)
Operator overloads version of condy::when_any.
The main namespace for the Condy library.
Definition condy.hpp:37
auto drain(Sender &&sender)
Mark an operation as drain operation.
auto link(Senders &&...senders)
Compose multiple operations into a single operation that executes them in sequence.
auto parallel(Senders &&...senders)
Compose multiple operations into a single sender that executes them in parallel.
auto hard_link(Senders &&...senders)
Compose multiple operations into a single operation that executes them in sequence and continues even...
auto when_any(Senders &&...senders)
Compose multiple operations into a single operation that completes when any of them complete.
auto when_all(Senders &&...senders)
Compose multiple operations into a single operation that completes when all of them complete.
auto flag(Sender &&sender)
Decorates an operation with specific io_uring sqe flags.
auto always_async(Sender &&sender)
Mark an operation to always execute asynchronously.
Sender types for composing asynchronous operations.