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 #include <stdlib.h>
20
21 #include <utility>
22
23 #include "src/core/lib/promise/detail/basic_seq.h"
24 #include "src/core/lib/promise/detail/promise_like.h"
25 #include "src/core/lib/promise/detail/seq_state.h"
26 #include "src/core/lib/promise/poll.h"
27 #include "src/core/util/debug_location.h"
28
29 namespace grpc_core {
30
31 namespace promise_detail {
32
33 template <typename T>
34 struct SeqTraits {
35 using UnwrappedType = T;
36 using WrappedType = T;
37 template <typename Next>
CallFactorySeqTraits38 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION static auto CallFactory(Next* next,
39 T&& value) {
40 return next->Make(std::forward<T>(value));
41 }
IsOkSeqTraits42 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION static bool IsOk(const T&) {
43 return true;
44 }
ErrorStringSeqTraits45 static const char* ErrorString(const T&) { abort(); }
46 template <typename R>
ReturnValueSeqTraits47 static R ReturnValue(T&&) {
48 abort();
49 }
50 template <typename Result, typename PriorResult, typename RunNext>
51 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION static Poll<Result>
CheckResultAndRunNextSeqTraits52 CheckResultAndRunNext(PriorResult prior, RunNext run_next) {
53 return run_next(std::move(prior));
54 }
55 };
56
57 template <typename P, typename... Fs>
58 class Seq {
59 public:
Seq(P && promise,Fs &&...factories,DebugLocation whence)60 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION explicit Seq(P&& promise,
61 Fs&&... factories,
62 DebugLocation whence)
63 : state_(std::forward<P>(promise), std::forward<Fs>(factories)...,
64 whence) {}
65
operator()66 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION auto operator()() {
67 return state_.PollOnce();
68 }
69
70 private:
71 SeqState<SeqTraits, P, Fs...> state_;
72 };
73
74 template <typename Iter, typename Factory, typename Argument>
75 using SeqIter = BasicSeqIter<SeqTraits, Iter, Factory, Argument>;
76
77 } // namespace promise_detail
78
79 // Sequencing combinator.
80 // Run the first promise.
81 // Pass its result to the second, and run the returned promise.
82 // Pass its result to the third, and run the returned promise.
83 // etc
84 // Return the final value.
85 template <typename F>
Seq(F functor)86 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline F Seq(F functor) {
87 return functor;
88 }
89
90 template <typename F0, typename F1>
91 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline promise_detail::Seq<F0, F1> Seq(
92 F0 f0, F1 f1, DebugLocation whence = {}) {
93 return promise_detail::Seq<F0, F1>(std::move(f0), std::move(f1), whence);
94 }
95
96 template <typename F0, typename F1, typename F2>
97 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline promise_detail::Seq<F0, F1, F2> Seq(
98 F0 f0, F1 f1, F2 f2, DebugLocation whence = {}) {
99 return promise_detail::Seq<F0, F1, F2>(std::move(f0), std::move(f1),
100 std::move(f2), whence);
101 }
102
103 template <typename F0, typename F1, typename F2, typename F3>
104 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline promise_detail::Seq<F0, F1, F2, F3>
105 Seq(F0 f0, F1 f1, F2 f2, F3 f3, DebugLocation whence = {}) {
106 return promise_detail::Seq<F0, F1, F2, F3>(
107 std::move(f0), std::move(f1), std::move(f2), std::move(f3), whence);
108 }
109
110 template <typename F0, typename F1, typename F2, typename F3, typename F4>
111 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline promise_detail::Seq<F0, F1, F2, F3,
112 F4>
113 Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, DebugLocation whence = {}) {
114 return promise_detail::Seq<F0, F1, F2, F3, F4>(std::move(f0), std::move(f1),
115 std::move(f2), std::move(f3),
116 std::move(f4), whence);
117 }
118
119 template <typename F0, typename F1, typename F2, typename F3, typename F4,
120 typename F5>
121 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline promise_detail::Seq<F0, F1, F2, F3,
122 F4, F5>
123 Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, DebugLocation whence = {}) {
124 return promise_detail::Seq<F0, F1, F2, F3, F4, F5>(
125 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
126 std::move(f5), whence);
127 }
128
129 template <typename F0, typename F1, typename F2, typename F3, typename F4,
130 typename F5, typename F6>
131 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION
132 promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6>
133 Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6,
134 DebugLocation whence = {}) {
135 return promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6>(
136 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
137 std::move(f5), std::move(f6), whence);
138 }
139
140 template <typename F0, typename F1, typename F2, typename F3, typename F4,
141 typename F5, typename F6, typename F7>
142 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION
143 promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7>
144 Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7,
145 DebugLocation whence = {}) {
146 return promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7>(
147 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
148 std::move(f5), std::move(f6), std::move(f7), whence);
149 }
150
151 template <typename F0, typename F1, typename F2, typename F3, typename F4,
152 typename F5, typename F6, typename F7, typename F8>
153 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION
154 promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8>
155 Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, F8 f8,
156 DebugLocation whence = {}) {
157 return promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8>(
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), std::move(f8), whence);
160 }
161
162 template <typename F0, typename F1, typename F2, typename F3, typename F4,
163 typename F5, typename F6, typename F7, typename F8, typename F9>
164 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION
165 promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9>
166 Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, F8 f8, F9 f9,
167 DebugLocation whence = {}) {
168 return promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9>(
169 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
170 std::move(f5), std::move(f6), std::move(f7), std::move(f8), std::move(f9),
171 whence);
172 }
173
174 template <typename F0, typename F1, typename F2, typename F3, typename F4,
175 typename F5, typename F6, typename F7, typename F8, typename F9,
176 typename F10>
177 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION
178 promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10>
179 Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, F8 f8, F9 f9,
180 F10 f10, DebugLocation whence = {}) {
181 return promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10>(
182 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
183 std::move(f5), std::move(f6), std::move(f7), std::move(f8), std::move(f9),
184 std::move(f10), whence);
185 }
186
187 template <typename F0, typename F1, typename F2, typename F3, typename F4,
188 typename F5, typename F6, typename F7, typename F8, typename F9,
189 typename F10, typename F11>
190 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION
191 promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11>
192 Seq(F0 f0, F1 f1, F2 f2, F3 f3, F4 f4, F5 f5, F6 f6, F7 f7, F8 f8, F9 f9,
193 F10 f10, F11 f11, DebugLocation whence = {}) {
194 return promise_detail::Seq<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11>(
195 std::move(f0), std::move(f1), std::move(f2), std::move(f3), std::move(f4),
196 std::move(f5), std::move(f6), std::move(f7), std::move(f8), std::move(f9),
197 std::move(f10), std::move(f11), whence);
198 }
199
200 // Execute a sequence of operations of unknown length.
201 // Asynchronously:
202 // for (element in (begin, end)) {
203 // argument = wait_for factory(element, argument);
204 // }
205 // return argument;
206 template <typename Iter, typename Factory, typename Argument>
SeqIter(Iter begin,Iter end,Argument argument,Factory factory)207 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION auto SeqIter(Iter begin, Iter end,
208 Argument argument,
209 Factory factory) {
210 return promise_detail::SeqIter<Iter, Factory, Argument>(
211 begin, end, std::move(factory), std::move(argument));
212 }
213
214 } // namespace grpc_core
215
216 #endif // GRPC_SRC_CORE_LIB_PROMISE_SEQ_H
217