mirror of https://github.com/grpc/grpc.git
Generic promise facilities (#26916)
* Poll type for promises library * Library to talk about things that look like promises if you squint * Promise helpers, and basic type erasure * build * Changes to sync required for promise activities * sanitized * Automated change: Fix sanity tests * suppressions * try to fix windows failure * Automated change: Fix sanity tests Co-authored-by: ctiller <ctiller@users.noreply.github.com>reviewable/pr26954/r4
parent
bb4311baed
commit
2e56b42ada
8 changed files with 246 additions and 16 deletions
@ -0,0 +1,86 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef GRPC_CORE_LIB_PROMISE_PROMISE_H |
||||
#define GRPC_CORE_LIB_PROMISE_PROMISE_H |
||||
|
||||
#include <grpc/impl/codegen/port_platform.h> |
||||
|
||||
#include <functional> |
||||
#include "absl/types/optional.h" |
||||
#include "src/core/lib/promise/detail/promise_like.h" |
||||
#include "src/core/lib/promise/poll.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
// A Promise is any functor that takes no arguments and returns Poll<T>.
|
||||
// Most of the time we just pass around the functor, but occasionally
|
||||
// it pays to have a type erased variant, which we define here.
|
||||
template <typename T> |
||||
using Promise = std::function<Poll<T>()>; |
||||
|
||||
// Helper to execute a promise immediately and return either the result or
|
||||
// nothing.
|
||||
template <typename Promise> |
||||
auto NowOrNever(Promise promise) |
||||
-> absl::optional<typename promise_detail::PromiseLike<Promise>::Result> { |
||||
auto r = promise_detail::PromiseLike<Promise>(std::move(promise))(); |
||||
if (auto* p = absl::get_if<kPollReadyIdx>(&r)) { |
||||
return std::move(*p); |
||||
} |
||||
return {}; |
||||
} |
||||
|
||||
// A promise that never completes.
|
||||
template <typename T> |
||||
struct Never { |
||||
Poll<T> operator()() { return Pending(); } |
||||
}; |
||||
|
||||
namespace promise_detail { |
||||
// A promise that immediately completes.
|
||||
template <typename T> |
||||
class Immediate { |
||||
public: |
||||
explicit Immediate(T value) : value_(std::move(value)) {} |
||||
|
||||
Poll<T> operator()() { return std::move(value_); } |
||||
|
||||
private: |
||||
T value_; |
||||
}; |
||||
|
||||
} // namespace promise_detail
|
||||
|
||||
// Return \a value immediately
|
||||
template <typename T> |
||||
promise_detail::Immediate<T> Immediate(T value) { |
||||
return promise_detail::Immediate<T>(std::move(value)); |
||||
} |
||||
|
||||
// Typecheck that a promise returns the expected return type.
|
||||
// usage: auto promise = WithResult<int>([]() { return 3; });
|
||||
// NOTE: there are tests in promise_test.cc that are commented out because they
|
||||
// should fail to compile. When modifying this code these should be uncommented
|
||||
// and their miscompilation verified.
|
||||
template <typename T, typename F> |
||||
auto WithResult(F f) -> |
||||
typename std::enable_if<std::is_same<decltype(f()), Poll<T>>::value, |
||||
F>::type { |
||||
return f; |
||||
} |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_CORE_LIB_PROMISE_PROMISE_H
|
@ -0,0 +1,42 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/core/lib/promise/promise.h" |
||||
#include <gtest/gtest.h> |
||||
|
||||
namespace grpc_core { |
||||
|
||||
TEST(PromiseTest, Works) { |
||||
Promise<int> x = []() { return 42; }; |
||||
EXPECT_EQ(x(), Poll<int>(42)); |
||||
} |
||||
|
||||
TEST(PromiseTest, Immediate) { EXPECT_EQ(Immediate(42)(), Poll<int>(42)); } |
||||
|
||||
TEST(PromiseTest, WithResult) { |
||||
EXPECT_EQ(WithResult<int>(Immediate(42))(), Poll<int>(42)); |
||||
// Fails to compile: WithResult<int>(Immediate(std::string("hello")));
|
||||
// Fails to compile: WithResult<int>(Immediate(42.9));
|
||||
} |
||||
|
||||
TEST(PromiseTest, NowOrNever) { |
||||
EXPECT_EQ(NowOrNever(Immediate(42)), absl::optional<int>(42)); |
||||
} |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) { |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
return RUN_ALL_TESTS(); |
||||
} |
Loading…
Reference in new issue