• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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