• 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_DETAIL_BASIC_SEQ_H
16 #define GRPC_SRC_CORE_LIB_PROMISE_DETAIL_BASIC_SEQ_H
17 
18 #include <grpc/support/port_platform.h>
19 
20 #include "src/core/lib/promise/detail/promise_factory.h"
21 #include "src/core/lib/promise/poll.h"
22 #include "src/core/util/construct_destruct.h"
23 
24 namespace grpc_core {
25 namespace promise_detail {
26 
27 template <typename FactoryFn>
BindFactoryFnArgs(FactoryFn fn)28 auto BindFactoryFnArgs(FactoryFn fn) {
29   return [fn = std::move(fn)](auto x) mutable {
30     return fn(std::get<0>(x), std::move(std::get<1>(x)));
31   };
32 }
33 
34 // Models a sequence of unknown size
35 // At each element, the accumulator A and the current value V is passed to some
36 // function of type IterTraits::Factory as f(V, IterTraits::Argument); f is
37 // expected to return a promise that resolves to IterTraits::Wrapped.
38 template <template <typename> class Traits, typename Iter, typename FactoryFn,
39           typename Argument>
40 class BasicSeqIter {
41  private:
42   using BoundFactoryFn = decltype(BindFactoryFnArgs(std::declval<FactoryFn>()));
43   using TplArg = std::tuple<decltype((*std::declval<Iter>())), Argument>;
44   using Factory = RepeatedPromiseFactory<TplArg, BoundFactoryFn>;
45   using State = typename Factory::Promise;
46   using StateResult = typename State::Result;
47 
48  public:
BasicSeqIter(Iter begin,Iter end,FactoryFn f,Argument arg)49   BasicSeqIter(Iter begin, Iter end, FactoryFn f, Argument arg)
50       : cur_(begin), end_(end), f_(BindFactoryFnArgs(std::move(f))) {
51     if (cur_ == end_) {
52       Construct(&result_, std::move(arg));
53     } else {
54       Construct(&state_, f_.Make(TplArg(*cur_, std::move(arg))));
55     }
56   }
57 
~BasicSeqIter()58   ~BasicSeqIter() {
59     if (cur_ == end_) {
60       Destruct(&result_);
61     } else {
62       Destruct(&state_);
63     }
64   }
65 
66   BasicSeqIter(const BasicSeqIter& other) = delete;
67   BasicSeqIter& operator=(const BasicSeqIter&) = delete;
68 
BasicSeqIter(BasicSeqIter && other)69   BasicSeqIter(BasicSeqIter&& other) noexcept
70       : cur_(other.cur_), end_(other.end_), f_(std::move(other.f_)) {
71     if (cur_ == end_) {
72       Construct(&result_, std::move(other.result_));
73     } else {
74       Construct(&state_, std::move(other.state_));
75     }
76   }
77   BasicSeqIter& operator=(BasicSeqIter&& other) noexcept {
78     cur_ = other.cur_;
79     end_ = other.end_;
80     if (cur_ == end_) {
81       Construct(&result_, std::move(other.result_));
82     } else {
83       Construct(&state_, std::move(other.state_));
84     }
85     return *this;
86   }
87 
operator()88   Poll<StateResult> operator()() {
89     if (cur_ == end_) {
90       return std::move(result_);
91     }
92     return PollNonEmpty();
93   }
94 
95  private:
PollNonEmpty()96   Poll<StateResult> PollNonEmpty() {
97     Poll<StateResult> r = state_();
98     if (r.pending()) return r;
99     using Tr = Traits<StateResult>;
100     return Tr::template CheckResultAndRunNext<StateResult>(
101         std::move(r.value()), [this](auto arg) -> Poll<StateResult> {
102           auto next = cur_;
103           ++next;
104           if (next == end_) {
105             return std::move(arg);
106           }
107           cur_ = next;
108           state_.~State();
109           struct WrapperFactory {
110             BasicSeqIter* owner;
111             State Make(typename Tr::UnwrappedType r) {
112               return owner->f_.Make(TplArg(*owner->cur_, std::move(r)));
113             }
114           };
115           WrapperFactory wrapper_factory{this};
116           Construct(&state_, Tr::CallFactory(&wrapper_factory, std::move(arg)));
117           return PollNonEmpty();
118         });
119   }
120 
121   Iter cur_;
122   const Iter end_;
123   GPR_NO_UNIQUE_ADDRESS Factory f_;
124   union {
125     GPR_NO_UNIQUE_ADDRESS State state_;
126     GPR_NO_UNIQUE_ADDRESS Argument result_;
127   };
128 };
129 
130 }  // namespace promise_detail
131 }  // namespace grpc_core
132 
133 #endif  // GRPC_SRC_CORE_LIB_PROMISE_DETAIL_BASIC_SEQ_H
134