• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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_PRIORITIZED_RACE_H
16 #define GRPC_SRC_CORE_LIB_PROMISE_PRIORITIZED_RACE_H
17 
18 #include <grpc/support/port_platform.h>
19 
20 #include <utility>
21 
22 namespace grpc_core {
23 
24 namespace promise_detail {
25 
26 template <typename A, typename B>
27 class TwoPartyPrioritizedRace {
28  public:
29   using Result = decltype(std::declval<A>()());
30 
TwoPartyPrioritizedRace(A a,B b)31   explicit TwoPartyPrioritizedRace(A a, B b)
32       : a_(std::move(a)), b_(std::move(b)) {}
33 
operator()34   Result operator()() {
35     // Check the priority promise.
36     auto p = a_();
37     if (p.ready()) return p;
38     // Check the other promise.
39     p = b_();
40     if (p.ready()) {
41       // re-poll a to see if it's also completed.
42       auto q = a_();
43       if (q.ready()) {
44         // both are ready, but a is prioritized
45         return q;
46       }
47     }
48     return p;
49   }
50 
51  private:
52   A a_;
53   B b_;
54 };
55 
56 template <typename... Promises>
57 class PrioritizedRace;
58 
59 template <typename Promise, typename... Promises>
60 class PrioritizedRace<Promise, Promises...>
61     : public TwoPartyPrioritizedRace<Promise, PrioritizedRace<Promises...>> {
62  public:
63   using Result = decltype(std::declval<Promise>()());
PrioritizedRace(Promise promise,Promises...promises)64   explicit PrioritizedRace(Promise promise, Promises... promises)
65       : TwoPartyPrioritizedRace<Promise, PrioritizedRace<Promises...>>(
66             std::move(promise),
67             PrioritizedRace<Promises...>(std::move(promises)...)) {}
68 };
69 
70 template <typename Promise>
71 class PrioritizedRace<Promise> {
72  public:
73   using Result = decltype(std::declval<Promise>()());
PrioritizedRace(Promise promise)74   explicit PrioritizedRace(Promise promise) : promise_(std::move(promise)) {}
operator()75   Result operator()() { return promise_(); }
76 
77  private:
78   Promise promise_;
79 };
80 
81 }  // namespace promise_detail
82 
83 /// Run all the promises until one is non-pending.
84 /// Once there's a non-pending promise, repoll all the promises before that.
85 /// Return the result from the lexically first non-pending promise.
86 template <typename... Promises>
PrioritizedRace(Promises...promises)87 promise_detail::PrioritizedRace<Promises...> PrioritizedRace(
88     Promises... promises) {
89   return promise_detail::PrioritizedRace<Promises...>(std::move(promises)...);
90 }
91 
92 }  // namespace grpc_core
93 
94 #endif  // GRPC_SRC_CORE_LIB_PROMISE_PRIORITIZED_RACE_H
95