xref: /aosp_15_r20/external/grpc-grpc/src/core/lib/promise/detail/basic_seq.h (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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/gprpp/construct_destruct.h"
21 #include "src/core/lib/promise/poll.h"
22 
23 namespace grpc_core {
24 namespace promise_detail {
25 
26 // Models a sequence of unknown size
27 // At each element, the accumulator A and the current value V is passed to some
28 // function of type IterTraits::Factory as f(V, IterTraits::Argument); f is
29 // expected to return a promise that resolves to IterTraits::Wrapped.
30 template <class IterTraits>
31 class BasicSeqIter {
32  private:
33   using Traits = typename IterTraits::Traits;
34   using Iter = typename IterTraits::Iter;
35   using Factory = typename IterTraits::Factory;
36   using Argument = typename IterTraits::Argument;
37   using IterValue = typename IterTraits::IterValue;
38   using StateCreated = typename IterTraits::StateCreated;
39   using State = typename IterTraits::State;
40   using Wrapped = typename IterTraits::Wrapped;
41 
42  public:
BasicSeqIter(Iter begin,Iter end,Factory f,Argument arg)43   BasicSeqIter(Iter begin, Iter end, Factory f, Argument arg)
44       : cur_(begin), end_(end), f_(std::move(f)) {
45     if (cur_ == end_) {
46       Construct(&result_, std::move(arg));
47     } else {
48       Construct(&state_, f_(*cur_, std::move(arg)));
49     }
50   }
51 
~BasicSeqIter()52   ~BasicSeqIter() {
53     if (cur_ == end_) {
54       Destruct(&result_);
55     } else {
56       Destruct(&state_);
57     }
58   }
59 
60   BasicSeqIter(const BasicSeqIter& other) = delete;
61   BasicSeqIter& operator=(const BasicSeqIter&) = delete;
62 
BasicSeqIter(BasicSeqIter && other)63   BasicSeqIter(BasicSeqIter&& other) noexcept
64       : cur_(other.cur_), end_(other.end_), f_(std::move(other.f_)) {
65     if (cur_ == end_) {
66       Construct(&result_, std::move(other.result_));
67     } else {
68       Construct(&state_, std::move(other.state_));
69     }
70   }
71   BasicSeqIter& operator=(BasicSeqIter&& other) noexcept {
72     cur_ = other.cur_;
73     end_ = other.end_;
74     if (cur_ == end_) {
75       Construct(&result_, std::move(other.result_));
76     } else {
77       Construct(&state_, std::move(other.state_));
78     }
79     return *this;
80   }
81 
operator()82   Poll<Wrapped> operator()() {
83     if (cur_ == end_) {
84       return std::move(result_);
85     }
86     return PollNonEmpty();
87   }
88 
89  private:
PollNonEmpty()90   Poll<Wrapped> PollNonEmpty() {
91     Poll<Wrapped> r = state_();
92     if (r.pending()) return r;
93     return Traits::template CheckResultAndRunNext<Wrapped>(
94         std::move(r.value()), [this](Wrapped arg) -> Poll<Wrapped> {
95           auto next = cur_;
96           ++next;
97           if (next == end_) {
98             return std::move(arg);
99           }
100           cur_ = next;
101           state_.~State();
102           Construct(&state_,
103                     Traits::template CallSeqFactory(f_, *cur_, std::move(arg)));
104           return PollNonEmpty();
105         });
106   }
107 
108   Iter cur_;
109   const Iter end_;
110   GPR_NO_UNIQUE_ADDRESS Factory f_;
111   union {
112     GPR_NO_UNIQUE_ADDRESS State state_;
113     GPR_NO_UNIQUE_ADDRESS Argument result_;
114   };
115 };
116 
117 }  // namespace promise_detail
118 }  // namespace grpc_core
119 
120 #endif  // GRPC_SRC_CORE_LIB_PROMISE_DETAIL_BASIC_SEQ_H
121