Condy v1.6.0
C++ Asynchronous System Call Layer for Linux
Loading...
Searching...
No Matches
senders.hpp
Go to the documentation of this file.
1
5
6#pragma once
7
8#include "condy/concepts.hpp"
9#include "condy/op_states.hpp"
10#include <array>
11#include <stdexcept>
12#include <tuple>
13#include <type_traits>
14#include <utility>
15#include <variant>
16#include <vector>
17
18namespace condy {
19
20template <PrepFuncLike PrepFunc, CQEHandlerLike CQEHandler> class OpSender {
21public:
22 using ReturnType = std::invoke_result_t<CQEHandler &, io_uring_cqe *>;
23
24 OpSender(PrepFunc func, CQEHandler cqe_handler)
25 : prep_func_(std::move(func)), cqe_handler_(std::move(cqe_handler)) {}
26
27 template <typename Receiver> auto connect(Receiver receiver) noexcept {
28 return detail::OpSenderOperationState<
29 OpFinishHandle<CQEHandler, Receiver>, PrepFunc>(
30 std::move(prep_func_), std::move(cqe_handler_),
31 std::move(receiver));
32 }
33
34private:
35 PrepFunc prep_func_;
36 CQEHandler cqe_handler_;
37};
38
39template <PrepFuncLike PrepFunc, CQEHandlerLike CQEHandler,
40 typename MultiShotFunc>
41class MultiShotOpSender {
42public:
43 using ReturnType = std::invoke_result_t<CQEHandler &, io_uring_cqe *>;
44
45 MultiShotOpSender(PrepFunc func, CQEHandler cqe_handler,
46 MultiShotFunc multi_shot_func)
47 : prep_func_(std::move(func)), cqe_handler_(std::move(cqe_handler)),
48 multi_shot_func_(std::move(multi_shot_func)) {}
49
50 template <typename Receiver> auto connect(Receiver receiver) noexcept {
51 return detail::OpSenderOperationState<
52 MultiShotOpFinishHandle<CQEHandler, MultiShotFunc, Receiver>,
53 PrepFunc>(std::move(prep_func_), std::move(cqe_handler_),
54 std::move(receiver), std::move(multi_shot_func_));
55 }
56
57private:
58 PrepFunc prep_func_;
59 CQEHandler cqe_handler_;
60 MultiShotFunc multi_shot_func_;
61};
62
63template <PrepFuncLike PrepFunc, CQEHandlerLike CQEHandler, typename FreeFunc>
64class ZeroCopyOpSender {
65public:
66 using ReturnType = std::invoke_result_t<CQEHandler &, io_uring_cqe *>;
67
68 ZeroCopyOpSender(PrepFunc func, CQEHandler cqe_handler, FreeFunc free_func)
69 : prep_func_(std::move(func)), cqe_handler_(std::move(cqe_handler)),
70 free_func_(std::move(free_func)) {}
71
72 template <typename Receiver> auto connect(Receiver receiver) noexcept {
73 return detail::OpSenderOperationState<
74 ZeroCopyOpFinishHandle<CQEHandler, FreeFunc, Receiver>, PrepFunc>(
75 std::move(prep_func_), std::move(cqe_handler_), std::move(receiver),
76 std::move(free_func_));
77 }
78
79private:
80 PrepFunc prep_func_;
81 CQEHandler cqe_handler_;
82 FreeFunc free_func_;
83};
84
85template <unsigned int Flags, typename Sender> class FlaggedOpSender {
86public:
87 using ReturnType = typename Sender::ReturnType;
88
89 FlaggedOpSender(Sender sender) : sender_(std::move(sender)) {}
90
91 template <typename Receiver> auto connect(Receiver receiver) noexcept {
92 return detail::FlaggedOpState<Flags, Sender, Receiver>(
93 std::move(sender_), std::move(receiver));
94 }
95
96private:
97 Sender sender_;
98};
99
100template <typename... Senders> class ParallelAllSender {
101public:
102 using ReturnType = std::pair<std::array<size_t, sizeof...(Senders)>,
103 std::tuple<typename Senders::ReturnType...>>;
104
105 ParallelAllSender(Senders... senders) : senders_(std::move(senders)...) {}
106
107 template <typename Receiver> auto connect(Receiver receiver) noexcept {
108 return detail::ParallelAllOperationState<Receiver, Senders...>(
109 std::move(senders_), std::move(receiver));
110 }
111
112private:
113 std::tuple<Senders...> senders_;
114};
115
116template <typename... Senders> class ParallelAnySender {
117public:
118 using ReturnType = std::pair<std::array<size_t, sizeof...(Senders)>,
119 std::tuple<typename Senders::ReturnType...>>;
120
121 ParallelAnySender(Senders... senders) : senders_(std::move(senders)...) {}
122
123 template <typename Receiver> auto connect(Receiver receiver) noexcept {
124 return detail::ParallelAnyOperationState<Receiver, Senders...>(
125 std::move(senders_), std::move(receiver));
126 }
127
128private:
129 std::tuple<Senders...> senders_;
130};
131
132template <typename... Senders> class WhenAllSender {
133public:
134 using ReturnType = std::tuple<typename Senders::ReturnType...>;
135
136 WhenAllSender(Senders... senders) : senders_(std::move(senders)...) {}
137
138 template <typename S, typename... Ss>
139 WhenAllSender(WhenAllSender<Ss...> other, S sender)
140 : senders_(std::tuple_cat(std::move(other.senders_),
141 std::make_tuple(std::move(sender)))) {}
142
143 template <typename Receiver> auto connect(Receiver receiver) noexcept {
144 return detail::WhenAllOperationState<Receiver, Senders...>(
145 std::move(senders_), std::move(receiver));
146 }
147
148private:
149 std::tuple<Senders...> senders_;
150
151 template <typename...> friend class WhenAllSender;
152};
153
154template <typename... Senders> class WhenAnySender {
155public:
156 using ReturnType = std::variant<typename Senders::ReturnType...>;
157
158 WhenAnySender(Senders... senders) : senders_(std::move(senders)...) {}
159
160 template <typename S, typename... Ss>
161 WhenAnySender(WhenAnySender<Ss...> other, S sender)
162 : senders_(std::tuple_cat(std::move(other.senders_),
163 std::make_tuple(std::move(sender)))) {}
164
165 template <typename Receiver> auto connect(Receiver receiver) noexcept {
166 return detail::WhenAnyOperationState<Receiver, Senders...>(
167 std::move(senders_), std::move(receiver));
168 }
169
170private:
171 std::tuple<Senders...> senders_;
172
173 template <typename...> friend class WhenAnySender;
174};
175
176template <unsigned int Flags, typename... Senders> class LinkSenderBase {
177public:
178 using ReturnType = std::tuple<typename Senders::ReturnType...>;
179
180 LinkSenderBase(Senders... senders) : senders_(std::move(senders)...) {}
181
182 template <typename S, typename... Ss>
183 LinkSenderBase(LinkSenderBase<Flags, Ss...> other, S sender)
184 : senders_(std::tuple_cat(std::move(other.senders_),
185 std::make_tuple(std::move(sender)))) {}
186
187 template <typename Receiver> auto connect(Receiver receiver) noexcept {
188 return detail::LinkOperationState<Receiver, Flags, Senders...>(
189 std::move(senders_), std::move(receiver));
190 }
191
192private:
193 std::tuple<Senders...> senders_;
194
195 template <unsigned int, typename...> friend class LinkSenderBase;
196};
197
198template <typename... Senders>
199using LinkSender = LinkSenderBase<IOSQE_IO_LINK, Senders...>;
200
201template <typename... Senders>
202using HardLinkSender = LinkSenderBase<IOSQE_IO_HARDLINK, Senders...>;
203
204template <typename Sender> class RangedParallelAllSender {
205public:
206 using ReturnType = std::pair<std::vector<size_t>,
207 std::vector<typename Sender::ReturnType>>;
208
209 RangedParallelAllSender(std::vector<Sender> senders)
210 : senders_(std::move(senders)) {}
211
212 template <typename Receiver> auto connect(Receiver receiver) noexcept {
213 return detail::RangedParallelAllOperationState<Receiver, Sender>(
214 std::move(senders_), std::move(receiver));
215 }
216
217private:
218 std::vector<Sender> senders_;
219};
220
221template <typename Sender> class RangedParallelAnySender {
222public:
223 using ReturnType = std::pair<std::vector<size_t>,
224 std::vector<typename Sender::ReturnType>>;
225
226 RangedParallelAnySender(std::vector<Sender> senders)
227 : senders_(std::move(senders)) {}
228
229 template <typename Receiver> auto connect(Receiver receiver) noexcept {
230 return detail::RangedParallelAnyOperationState<Receiver, Sender>(
231 std::move(senders_), std::move(receiver));
232 }
233
234private:
235 std::vector<Sender> senders_;
236};
237
238template <typename Sender> class RangedWhenAllSender {
239public:
240 using ReturnType = std::vector<typename Sender::ReturnType>;
241
242 RangedWhenAllSender(std::vector<Sender> senders)
243 : senders_(std::move(senders)) {}
244
245 template <typename Receiver> auto connect(Receiver receiver) noexcept {
246 return detail::WhenAllRangeOperationState<Receiver, Sender>(
247 std::move(senders_), std::move(receiver));
248 }
249
250private:
251 std::vector<Sender> senders_;
252};
253
254template <typename Sender> class RangedWhenAnySender {
255public:
256 using ReturnType = std::pair<size_t, typename Sender::ReturnType>;
257
258 RangedWhenAnySender(std::vector<Sender> senders)
259 : senders_(std::move(senders)) {
260 if (senders_.empty()) {
261 throw std::invalid_argument(
262 "when_any requires at least one sender");
263 }
264 }
265
266 template <typename Receiver> auto connect(Receiver receiver) noexcept {
267 return detail::WhenAnyRangeOperationState<Receiver, Sender>(
268 std::move(senders_), std::move(receiver));
269 }
270
271private:
272 std::vector<Sender> senders_;
273};
274
275template <unsigned int Flags, typename Sender> class RangedLinkSenderBase {
276public:
277 using ReturnType = std::vector<typename Sender::ReturnType>;
278
279 RangedLinkSenderBase(std::vector<Sender> senders)
280 : senders_(std::move(senders)) {}
281
282 template <typename Receiver> auto connect(Receiver receiver) noexcept {
283 return detail::RangedLinkOperationState<Receiver, Flags, Sender>(
284 std::move(senders_), std::move(receiver));
285 }
286
287private:
288 std::vector<Sender> senders_;
289};
290
291template <typename Sender>
292using RangedLinkSender = RangedLinkSenderBase<IOSQE_IO_LINK, Sender>;
293
294template <typename Sender>
295using RangedHardLinkSender = RangedLinkSenderBase<IOSQE_IO_HARDLINK, Sender>;
296
297} // namespace condy
The main namespace for the Condy library.
Definition condy.hpp:30
Operation state implementations for various operations.