1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef GRPC_SRC_CORE_LIB_PROMISE_SEQ_H
16 #define GRPC_SRC_CORE_LIB_PROMISE_SEQ_H
17
18 #include <grpc/support/port_platform.h>
19
20 #include <stdlib.h>
21
22 #include <utility>
23
24 #include "src/core/lib/gprpp/debug_location.h"
25 #include "src/core/lib/promise/detail/basic_seq.h"
26 #include "src/core/lib/promise/detail/promise_like.h"
27 #include "src/core/lib/promise/detail/seq_state.h"
28 #include "src/core/lib/promise/poll.h"
29
30 namespace grpc_core {
31
32 namespace promise_detail {
33
34 template <typename T>
35 struct SeqTraits {
36 using UnwrappedType = T;
37 using WrappedType = T;
38 template <typename Next>
CallFactorySeqTraits39 static auto CallFactory(Next* next, T&& value) {
40 return next->Make(std::forward<T>(value));
41 }
IsOkSeqTraits42 static bool IsOk(const T&) { return true; }
ErrorStringSeqTraits43 static const char* ErrorString(const T&) { abort(); }
44 template <typename R>
ReturnValueSeqTraits45 static R ReturnValue(T&&) {
46 abort();
47 }
48 template <typename F, typename Elem>
CallSeqFactorySeqTraits49 static auto CallSeqFactory(F& f, Elem&& elem, T&& value) {
50 return f(std::forward<Elem>(elem), std::forward<T>(value));
51 }
52 template <typename Result, typename PriorResult, typename RunNext>
CheckResultAndRunNextSeqTraits53 static Poll<Result> CheckResultAndRunNext(PriorResult prior,
54 RunNext run_next) {
55 return run_next(std::move(prior));
56 }
57 };
58
59 template <typename P, typename... Fs>
60 class Seq {
61 public:
Seq(P && promise,Fs &&...factories,DebugLocation whence)62 explicit Seq(P&& promise, Fs&&... factories, DebugLocation whence)
63 : state_(std::forward<P>(promise), std::forward<Fs>(factories)...,
64 whence) {}
65
operator()66 auto operator()() { return state_.PollOnce(); }
67
68 private:
69 SeqState<SeqTraits, P, Fs...> state_;
70 };
71
72 template <typename I, typename F, typename Arg>
73 struct SeqIterTraits {
74 using Iter = I;
75 using Factory = F;
76 using Argument = Arg;
77 using IterValue = decltype(*std::declval<Iter>());
78 using StateCreated = decltype(std::declval<F>()(std::declval<IterValue>(),
79 std::declval<Arg>()));
80 using State = PromiseLike<StateCreated>;
81 using Wrapped = typename State::Result;
82
83 using Traits = SeqTraits<Wrapped>;
84 };
85
86 template <typename Iter, typename Factory, typename Argument>
87 struct SeqIterResultTraits {
88 using IterTraits = SeqIterTraits<Iter, Factory, Argument>;
89 using Result = BasicSeqIter<IterTraits>;
90 };
91
92 } // namespace promise_detail
93
94 // Sequencing combinator.
95 // Run the first promise.
96 // Pass its result to the second, and run the returned promise.
97 // Pass its result to the third, and run the returned promise.
98 // etc
99 // Return the final value.
100 template <typename F>
Seq(F functor)101 F Seq(F functor) {
102 return functor;
103 }
104
105 template <typename F0, typename F1>
106 promise_detail::Seq<F0, F1> Seq(F0 f0, F1 f1, DebugLocation whence = {}) {
107 return promise_detail::Seq<F0, F1>(std::move(f0), std::move(f1), whence);
108 }
109
110 template <typename F0, typename F1, typename F2>
111 promise_detail::Seq<F0, F1, F2> Seq(F0 f0, F1 f1, F2 f2,
112 DebugLocation whence = {}) {
113 return promise_detail::Seq<F0, F1, F2>(std::move(f0), std::move(f1),
114 std::move(f2), whence);
115 }
116
117 template <typename F0, typename F1, typename F2, typename F3>
118 promise_detail::Seq<F0, F1, F2, F3> Seq(F0 f0, F1 f1, F2 f2, F3 f3,
119 DebugLocation whence = {}) {
120 return promise_detail::Seq<F0, F1, F2, F3>(
121 std::move(f0), std::move(f1), std::move(f2), std::move(f3), whence);
122 }
123
124 template <typename F0, typename F1, typename F2, typename F3, typename F4>
125 promise_detail::Seq<F0, F1, F2, F3, F4> Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4,
126 DebugLocation whence = {}) {
127 return promise_detail::Seq<F0, F1, F2, F3, F4>(std::move(f0), std::move(f1),
128 std::move(f2), std::move(f3),
129 std::move(f4), whence);
130 }
131
132 template <typename F0, typename F1, typename F2, typename F3, typename F4,
133 typename F5>
134 promise_detail::Seq<F0, F1, F2, F3, F4, F5> Seq(F0 f0, F1 f1, F2 f2, F3 f3,
135 F4 f4, F5 f5,
136 DebugLocation whence = {}) {
137 return promise_detail::Seq<F0, F1, F2, F3, F4, F5>(
138 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
139 std::move(f5), whence);
140 }
141
142 template <typename F0, typename F1, typename F2, typename F3, typename F4,
143 typename F5, typename F6>
144 promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6> Seq(F0 f0, F1 f1, F2 f2, F3 f3,
145 F4 f4, F5 f5, F6 f6,
146 DebugLocation whence = {}) {
147 return promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6>(
148 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
149 std::move(f5), std::move(f6), whence);
150 }
151
152 template <typename F0, typename F1, typename F2, typename F3, typename F4,
153 typename F5, typename F6, typename F7>
154 promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7> Seq(
155 F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7,
156 DebugLocation whence = {}) {
157 return promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7>(
158 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
159 std::move(f5), std::move(f6), std::move(f7), whence);
160 }
161
162 template <typename F0, typename F1, typename F2, typename F3, typename F4,
163 typename F5, typename F6, typename F7, typename F8>
164 promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8> Seq(
165 F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, F8 f8,
166 DebugLocation whence = {}) {
167 return promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8>(
168 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
169 std::move(f5), std::move(f6), std::move(f7), std::move(f8), whence);
170 }
171
172 template <typename F0, typename F1, typename F2, typename F3, typename F4,
173 typename F5, typename F6, typename F7, typename F8, typename F9>
174 promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9> Seq(
175 F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, F8 f8, F9 f9,
176 DebugLocation whence = {}) {
177 return promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9>(
178 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
179 std::move(f5), std::move(f6), std::move(f7), std::move(f8), std::move(f9),
180 whence);
181 }
182
183 template <typename F0, typename F1, typename F2, typename F3, typename F4,
184 typename F5, typename F6, typename F7, typename F8, typename F9,
185 typename F10>
186 promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10> Seq(
187 F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, F8 f8, F9 f9,
188 F10 f10, DebugLocation whence = {}) {
189 return promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10>(
190 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
191 std::move(f5), std::move(f6), std::move(f7), std::move(f8), std::move(f9),
192 std::move(f10), whence);
193 }
194
195 template <typename F0, typename F1, typename F2, typename F3, typename F4,
196 typename F5, typename F6, typename F7, typename F8, typename F9,
197 typename F10, typename F11>
198 promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11> Seq(
199 F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, F8 f8, F9 f9,
200 F10 f10, F11 f11, DebugLocation whence = {}) {
201 return promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11>(
202 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
203 std::move(f5), std::move(f6), std::move(f7), std::move(f8), std::move(f9),
204 std::move(f10), std::move(f11), whence);
205 }
206
207 // Execute a sequence of operations of unknown length.
208 // Asynchronously:
209 // for (element in (begin, end)) {
210 // argument = wait_for factory(element, argument);
211 // }
212 // return argument;
213 template <typename Iter, typename Factory, typename Argument>
214 typename promise_detail::SeqIterResultTraits<Iter, Factory, Argument>::Result
SeqIter(Iter begin,Iter end,Argument argument,Factory factory)215 SeqIter(Iter begin, Iter end, Argument argument, Factory factory) {
216 using Result = typename promise_detail::SeqIterResultTraits<Iter, Factory,
217 Argument>::Result;
218 return Result(begin, end, std::move(factory), std::move(argument));
219 }
220
221 } // namespace grpc_core
222
223 #endif // GRPC_SRC_CORE_LIB_PROMISE_SEQ_H
224