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_RACE_H
16 #define GRPC_SRC_CORE_LIB_PROMISE_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 // Implementation type for Race combinator.
27 template <typename... Promises>
28 class Race;
29
30 template <typename Promise, typename... Promises>
31 class Race<Promise, Promises...> {
32 public:
33 using Result = decltype(std::declval<Promise>()());
34
Race(Promise promise,Promises...promises)35 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION explicit Race(Promise promise,
36 Promises... promises)
37 : promise_(std::move(promise)), next_(std::move(promises)...) {}
38
operator()39 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Result operator()() {
40 // Check our own promise.
41 auto r = promise_();
42 if (r.pending()) {
43 // Check the rest of them.
44 return next_();
45 }
46 // Return the first ready result.
47 return std::move(r.value());
48 }
49
50 private:
51 // The Promise checked by this instance.
52 Promise promise_;
53 // We recursively expand to check the rest of the instances.
54 Race<Promises...> next_;
55 };
56
57 template <typename Promise>
58 class Race<Promise> {
59 public:
60 using Result = decltype(std::declval<Promise>()());
Race(Promise promise)61 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION explicit Race(Promise promise)
62 : promise_(std::move(promise)) {}
operator()63 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Result operator()() {
64 return promise_();
65 }
66
67 private:
68 Promise promise_;
69 };
70
71 } // namespace promise_detail
72
73 /// Run all the promises, return the first result that's available.
74 /// If two results are simultaneously available, bias towards the first result
75 /// listed.
76 template <typename... Promises>
77 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline promise_detail::Race<Promises...>
Race(Promises...promises)78 Race(Promises... promises) {
79 return promise_detail::Race<Promises...>(std::move(promises)...);
80 }
81
82 } // namespace grpc_core
83
84 #endif // GRPC_SRC_CORE_LIB_PROMISE_RACE_H
85