Condy v1.8
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"
10#include <array>
11#include <tuple>
12#include <type_traits>
13#include <utility>
14#include <variant>
15#include <vector>
16
17namespace condy {
18namespace detail {
19
20template <PrepFuncLike PrepFunc, CQEHandlerLike CQEHandler,
21 template <typename...> class FinishHandle, typename... Args>
22class [[nodiscard]] OpSenderBase {
23public:
24 using CondySender = void;
25 using ReturnType = std::invoke_result_t<CQEHandler &, io_uring_cqe *>;
26
27 OpSenderBase(PrepFunc func, CQEHandler cqe_handler, Args... args)
28 : prep_func_(std::move(func)), cqe_handler_(std::move(cqe_handler)),
29 args_(std::make_tuple(std::move(args)...)) {}
30
31 template <typename Receiver> auto connect_impl(Receiver receiver) noexcept {
32 return std::apply(
33 [&](auto &&...args) {
34 return OpSenderOperationState<
35 FinishHandle<CQEHandler, Args..., Receiver>, PrepFunc>(
36 std::move(prep_func_), std::move(cqe_handler_),
37 std::move(receiver), std::forward<decltype(args)>(args)...);
38 },
39 std::move(args_));
40 }
41
42private:
43 PrepFunc prep_func_;
44 CQEHandler cqe_handler_;
45 std::tuple<Args...> args_;
46};
47
48template <PrepFuncLike PrepFunc, CQEHandlerLike CQEHandler>
49using OpSender = OpSenderBase<PrepFunc, CQEHandler, OpFinishHandle>;
50
51template <PrepFuncLike PrepFunc, CQEHandlerLike CQEHandler,
52 typename MultiShotFunc>
53using MultiShotOpSender =
54 OpSenderBase<PrepFunc, CQEHandler, MultiShotOpFinishHandle, MultiShotFunc>;
55
56template <PrepFuncLike PrepFunc, CQEHandlerLike CQEHandler, typename FreeFunc>
57using ZeroCopyOpSender =
58 OpSenderBase<PrepFunc, CQEHandler, ZeroCopyOpFinishHandle, FreeFunc>;
59
60template <unsigned int Flags, typename Sender>
61class [[nodiscard]] FlaggedOpSender {
62public:
63 using CondySender = void;
64 using ReturnType = typename Sender::ReturnType;
65
66 FlaggedOpSender(Sender sender) : sender_(std::move(sender)) {}
67
68 template <typename Receiver> auto connect_impl(Receiver receiver) noexcept {
69 return FlaggedOpState<Flags, Sender, Receiver>(std::move(sender_),
70 std::move(receiver));
71 }
72
73private:
74 Sender sender_;
75};
76
77template <template <typename, unsigned int, typename...> class OperationState,
78 unsigned int Flags>
79struct link_sender_helper {
80 template <typename Receiver, typename... Senders>
81 using apply = OperationState<Receiver, Flags, Senders...>;
82};
83
84template <typename Return, template <typename...> class OperationState,
85 typename... Senders>
86class [[nodiscard]] ParallelSenderBase {
87public:
88 using CondySender = void;
89 using ReturnType = Return;
90
91 ParallelSenderBase(Senders... senders) : senders_(std::move(senders)...) {}
92
93 template <typename PrevReturn, typename S, typename... Ss>
94 ParallelSenderBase(
95 ParallelSenderBase<PrevReturn, OperationState, Ss...> &&other, S sender)
96 : senders_(std::tuple_cat(std::move(other.senders_),
97 std::make_tuple(std::move(sender)))) {}
98
99 template <typename Receiver> auto connect_impl(Receiver receiver) noexcept {
100 return OperationState<Receiver, Senders...>(std::move(senders_),
101 std::move(receiver));
102 }
103
104private:
105 std::tuple<Senders...> senders_;
106
107 template <typename, template <typename...> class, typename...>
108 friend class ParallelSenderBase;
109};
110
111template <typename... Senders>
112using ParallelAllSender =
113 ParallelSenderBase<std::pair<std::array<size_t, sizeof...(Senders)>,
114 std::tuple<typename Senders::ReturnType...>>,
115 ParallelAllOperationState, Senders...>;
116
117template <typename... Senders>
118using ParallelAnySender =
119 ParallelSenderBase<std::pair<std::array<size_t, sizeof...(Senders)>,
120 std::tuple<typename Senders::ReturnType...>>,
121 ParallelAnyOperationState, Senders...>;
122
123template <typename... Senders>
124using WhenAllSender =
125 ParallelSenderBase<std::tuple<typename Senders::ReturnType...>,
126 WhenAllOperationState, Senders...>;
127
128template <typename... Senders>
129using WhenAnySender =
130 ParallelSenderBase<std::variant<typename Senders::ReturnType...>,
131 WhenAnyOperationState, Senders...>;
132
133template <unsigned int Flags, typename... Senders>
134using LinkSenderBase = ParallelSenderBase<
135 std::tuple<typename Senders::ReturnType...>,
136 link_sender_helper<LinkOperationState, Flags>::template apply, Senders...>;
137
138template <typename... Senders>
139using LinkSender = LinkSenderBase<IOSQE_IO_LINK, Senders...>;
140
141template <typename... Senders>
142using HardLinkSender = LinkSenderBase<IOSQE_IO_HARDLINK, Senders...>;
143
144template <typename Return, template <typename...> class OperationState,
145 typename Sender>
146class [[nodiscard]] RangedParallelSenderBase {
147public:
148 using CondySender = void;
149 using ReturnType = Return;
150
151 RangedParallelSenderBase(std::vector<Sender> senders)
152 : senders_(std::move(senders)) {}
153
154 template <typename Receiver> auto connect_impl(Receiver receiver) noexcept {
155 return OperationState<Receiver, Sender>(std::move(senders_),
156 std::move(receiver));
157 }
158
159private:
160 std::vector<Sender> senders_;
161};
162
163template <typename Sender>
164using RangedParallelAllSender = RangedParallelSenderBase<
165 std::pair<std::vector<size_t>, std::vector<typename Sender::ReturnType>>,
166 RangedParallelAllOperationState, Sender>;
167
168template <typename Sender>
169using RangedParallelAnySender = RangedParallelSenderBase<
170 std::pair<std::vector<size_t>, std::vector<typename Sender::ReturnType>>,
171 RangedParallelAnyOperationState, Sender>;
172
173template <typename Sender>
174using RangedWhenAllSender =
175 RangedParallelSenderBase<std::vector<typename Sender::ReturnType>,
176 RangedWhenAllOperationState, Sender>;
177
178template <typename Sender>
179using RangedWhenAnySender =
180 RangedParallelSenderBase<std::pair<size_t, typename Sender::ReturnType>,
181 RangedWhenAnyOperationState, Sender>;
182
183template <unsigned int Flags, typename Sender>
184using RangedLinkSenderBase = RangedParallelSenderBase<
185 std::vector<typename Sender::ReturnType>,
186 link_sender_helper<RangedLinkOperationState, Flags>::template apply,
187 Sender>;
188
189template <typename Sender>
190using RangedLinkSender = RangedLinkSenderBase<IOSQE_IO_LINK, Sender>;
191
192template <typename Sender>
193using RangedHardLinkSender = RangedLinkSenderBase<IOSQE_IO_HARDLINK, Sender>;
194
195} // namespace detail
196} // namespace condy
The main namespace for the Condy library.
Definition condy.hpp:37
Operation state implementations for various operations.