call_push_pull.h
Go to the documentation of this file.
1 // Copyright 2022 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_CORE_LIB_PROMISE_CALL_PUSH_PULL_H
16 #define GRPC_CORE_LIB_PROMISE_CALL_PUSH_PULL_H
17 
19 
20 #include <assert.h>
21 
22 #include <type_traits>
23 
24 #include "absl/types/variant.h"
25 
31 
32 namespace grpc_core {
33 
34 namespace promise_detail {
35 
36 template <typename FMain, typename FPush, typename FPull>
37 class CallPushPull {
38  public:
39  CallPushPull(FMain f_main, FPush f_push, FPull f_pull)
40  : push_(std::move(f_push)), pull_(std::move(f_pull)) {
41  Construct(&main_, std::move(f_main));
42  }
43 
44  CallPushPull(const CallPushPull&) = delete;
45  CallPushPull& operator=(const CallPushPull&) = delete;
46  CallPushPull(CallPushPull&& other) noexcept
47  : done_(other.done_),
48  push_(std::move(other.push_)),
49  pull_(std::move(other.pull_)) {
50  assert(!done_.is_set(kDoneMain));
51  Construct(&main_, std::move(other.main_));
52  }
53 
54  CallPushPull& operator=(CallPushPull&& other) noexcept {
55  assert(!done_.is_set(kDoneMain));
56  done_ = other.done_;
57  assert(!done_.is_set(kDoneMain));
58  push_ = std::move(other.push_);
59  main_ = std::move(other.main_);
60  pull_ = std::move(other.pull_);
61  return *this;
62  }
63 
65  if (done_.is_set(kDoneMain)) {
66  Destruct(&result_);
67  } else {
68  Destruct(&main_);
69  }
70  }
71 
72  using Result =
73  typename PollTraits<decltype(std::declval<PromiseLike<FMain>>()())>::Type;
74 
76  if (!done_.is_set(kDonePush)) {
77  auto p = push_();
78  if (auto* status = absl::get_if<kPollReadyIdx>(&p)) {
79  if (IsStatusOk(*status)) {
81  } else {
82  return Result(std::move(*status));
83  }
84  }
85  }
86  if (!done_.is_set(kDoneMain)) {
87  auto p = main_();
88  if (auto* status = absl::get_if<kPollReadyIdx>(&p)) {
89  if (IsStatusOk(*status)) {
91  Destruct(&main_);
93  } else {
94  return std::move(*status);
95  }
96  }
97  }
98  if (!done_.is_set(kDonePull)) {
99  auto p = pull_();
100  if (auto* status = absl::get_if<kPollReadyIdx>(&p)) {
101  if (IsStatusOk(*status)) {
103  } else {
104  return Result(std::move(*status));
105  }
106  }
107  }
108  if (done_.all()) return std::move(result_);
109  return Pending{};
110  }
111 
112  private:
113  enum { kDonePull = 0, kDoneMain = 1, kDonePush = 2 };
116  union {
119  };
121 };
122 
123 } // namespace promise_detail
124 
125 // For promises representing calls a common pattern emerges:
126 // There's a process pushing data down the stack, a process handling the main
127 // call part, and a process pulling data back up the stack.
128 //
129 // This can reasonably be represented by the right combinations of TryJoins and
130 // Maps, but since the structure is fundamental to the domain we introduce
131 // this simple helper to make it easier to write the common case.
132 //
133 // It takes three promises: the main call, the push and the pull.
134 // When polling, the push is polled first, then the main call (descending the
135 // stack), then the pull (as we ascend once more).
136 //
137 // This strategy minimizes repolls.
138 template <typename FMain, typename FPush, typename FPull>
140  FPush f_push,
141  FPull f_pull) {
143  std::move(f_main), std::move(f_push), std::move(f_pull));
144 }
145 
146 } // namespace grpc_core
147 
148 #endif // GRPC_CORE_LIB_PROMISE_CALL_PUSH_PULL_H
grpc_core::promise_detail::CallPushPull::kDonePull
@ kDonePull
Definition: call_push_pull.h:113
Type
struct Type Type
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:673
grpc_core::promise_detail::CallPushPull::CallPushPull
CallPushPull(FMain f_main, FPush f_push, FPull f_pull)
Definition: call_push_pull.h:39
grpc_core::promise_detail::CallPushPull::Result
typename PollTraits< decltype(std::declval< PromiseLike< FMain > >()())>::Type Result
Definition: call_push_pull.h:73
grpc_core::promise_detail::CallPushPull
Definition: call_push_pull.h:37
grpc_core::BitSet::set
GRPC_BITSET_CONSTEXPR_MUTATOR void set(int i)
Definition: bitset.h:93
grpc_core
Definition: call_metric_recorder.h:31
grpc_core::IsStatusOk
bool IsStatusOk(const absl::Status &status)
Definition: src/core/lib/promise/detail/status.h:46
status
absl::Status status
Definition: rls.cc:251
grpc_core::promise_detail::CallPushPull::operator()
Poll< Result > operator()()
Definition: call_push_pull.h:75
grpc_core::promise_detail::CallPushPull::kDonePush
@ kDonePush
Definition: call_push_pull.h:113
grpc_core::promise_detail::CallPushPull::CallPushPull
CallPushPull(CallPushPull &&other) noexcept
Definition: call_push_pull.h:46
grpc_core::BitSet::is_set
constexpr bool is_set(int i) const
Definition: bitset.h:112
grpc_core::CallPushPull
promise_detail::CallPushPull< FMain, FPush, FPull > CallPushPull(FMain f_main, FPush f_push, FPull f_pull)
Definition: call_push_pull.h:139
grpc_core::Pending
Definition: poll.h:29
grpc_core::promise_detail::CallPushPull::operator=
CallPushPull & operator=(CallPushPull &&other) noexcept
Definition: call_push_pull.h:54
grpc_core::promise_detail::CallPushPull::push_
GPR_NO_UNIQUE_ADDRESS PromiseLike< FPush > push_
Definition: call_push_pull.h:115
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
grpc_core::promise_detail::CallPushPull::pull_
GPR_NO_UNIQUE_ADDRESS PromiseLike< FPull > pull_
Definition: call_push_pull.h:120
grpc_core::promise_detail::CallPushPull::done_
BitSet< 3 > done_
Definition: call_push_pull.h:114
grpc_core::PollTraits
Definition: poll.h:54
GPR_NO_UNIQUE_ADDRESS
#define GPR_NO_UNIQUE_ADDRESS
Definition: impl/codegen/port_platform.h:692
grpc_core::promise_detail::CallPushPull::result_
Result result_
Definition: call_push_pull.h:118
grpc_core::Construct
void Construct(T *p, Args &&... args)
Definition: construct_destruct.h:34
grpc_core::Destruct
void Destruct(T *p)
Definition: construct_destruct.h:27
grpc_core::BitSet< 3 >
promise_like.h
poll.h
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
grpc_core::BitSet::all
bool all() const
Definition: bitset.h:117
status.h
grpc_core::promise_detail::CallPushPull::main_
PromiseLike< FMain > main_
Definition: call_push_pull.h:117
grpc_core::promise_detail::CallPushPull::~CallPushPull
~CallPushPull()
Definition: call_push_pull.h:64
grpc_core::promise_detail::CallPushPull::operator=
CallPushPull & operator=(const CallPushPull &)=delete
absl::variant
Definition: abseil-cpp/absl/types/internal/variant.h:46
grpc_core::promise_detail::PromiseLike< FMain >
grpc_core::promise_detail::CallPushPull::kDoneMain
@ kDoneMain
Definition: call_push_pull.h:113
construct_destruct.h
bitset.h
port_platform.h


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:42