• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_PROMISE_H
16 #define GRPC_SRC_CORE_LIB_PROMISE_PROMISE_H
17 
18 #include <grpc/support/port_platform.h>
19 
20 #include <type_traits>
21 
22 #include "absl/functional/any_invocable.h"
23 #include "absl/log/log.h"
24 #include "absl/status/status.h"
25 #include "absl/types/optional.h"
26 #include "src/core/lib/promise/detail/promise_like.h"
27 #include "src/core/lib/promise/poll.h"
28 
29 namespace grpc_core {
30 
31 // A Promise is any functor that takes no arguments and returns Poll<T>.
32 // Most of the time we just pass around the functor, but occasionally
33 // it pays to have a type erased variant, which we define here.
34 template <typename T>
35 using Promise = absl::AnyInvocable<Poll<T>()>;
36 
37 // Helper to execute a promise immediately and return either the result or
38 // nothing.
39 template <typename Promise>
40 auto NowOrNever(Promise promise)
41     -> absl::optional<typename promise_detail::PromiseLike<Promise>::Result> {
42   auto r = promise_detail::PromiseLike<Promise>(std::move(promise))();
43   if (auto* p = r.value_if_ready()) {
44     return std::move(*p);
45   }
46   return {};
47 }
48 
49 // A promise that never completes.
50 template <typename T>
51 struct Never {
operatorNever52   Poll<T> operator()() { return Pending(); }
53 };
54 
55 namespace promise_detail {
56 // A promise that immediately completes.
57 template <typename T>
58 class Immediate {
59  public:
Immediate(T value)60   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION explicit Immediate(T value)
61       : value_(std::move(value)) {}
62 
operator()63   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Poll<T> operator()() {
64     return std::move(value_);
65   }
66 
67  private:
68   T value_;
69 };
70 }  // namespace promise_detail
71 
72 // Return \a value immediately
73 template <typename T>
74 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline promise_detail::Immediate<T>
Immediate(T value)75 Immediate(T value) {
76   return promise_detail::Immediate<T>(std::move(value));
77 }
78 
79 // Return status Ok immediately
80 struct ImmediateOkStatus {
operatorImmediateOkStatus81   GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION Poll<absl::Status> operator()() {
82     return absl::OkStatus();
83   }
84 };
85 
86 // Typecheck that a promise returns the expected return type.
87 // usage: auto promise = WithResult<int>([]() { return 3; });
88 // NOTE: there are tests in promise_test.cc that are commented out because they
89 // should fail to compile. When modifying this code these should be uncommented
90 // and their miscompilation verified.
91 template <typename T, typename F>
92 GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline auto WithResult(F f) ->
93     typename std::enable_if<std::is_same<decltype(f()), Poll<T>>::value,
94                             F>::type {
95   return f;
96 }
97 
98 template <typename Promise>
99 using PromiseResult = typename PollTraits<
100     typename promise_detail::PromiseLike<Promise>::Result>::Type;
101 
102 }  // namespace grpc_core
103 
104 #endif  // GRPC_SRC_CORE_LIB_PROMISE_PROMISE_H
105