• 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 
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