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