Promises race (#26915)

* Poll type for promises library

* Promises race construct

* Changes to sync required for promise activities

* Automated change: Fix sanity tests

* fix

Co-authored-by: ctiller <ctiller@users.noreply.github.com>
pull/27073/head
Craig Tiller 4 years ago committed by GitHub
parent 52fece38e6
commit 4744aceb68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      BUILD
  2. 36
      CMakeLists.txt
  3. 12
      build_autogenerated.yaml
  4. 80
      src/core/lib/promise/race.h
  5. 12
      test/core/promise/BUILD
  6. 32
      test/core/promise/race_test.cc
  7. 24
      tools/run_tests/generated/tests.json

10
BUILD

@ -949,6 +949,16 @@ grpc_cc_library(
deps = ["gpr_platform"],
)
grpc_cc_library(
name = "race",
language = "c++",
public_hdrs = ["src/core/lib/promise/race.h"],
deps = [
"gpr_platform",
"poll",
],
)
grpc_cc_library(
name = "switch",
language = "c++",

36
CMakeLists.txt generated

@ -923,6 +923,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx proto_utils_test)
add_dependencies(buildtests_cxx qps_json_driver)
add_dependencies(buildtests_cxx qps_worker)
add_dependencies(buildtests_cxx race_test)
add_dependencies(buildtests_cxx raw_end2end_test)
add_dependencies(buildtests_cxx rbac_translator_test)
add_dependencies(buildtests_cxx ref_counted_ptr_test)
@ -13413,6 +13414,41 @@ target_link_libraries(qps_worker
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(race_test
test/core/promise/race_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(race_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(race_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::variant
)
endif()
if(gRPC_BUILD_TESTS)

@ -6244,6 +6244,18 @@ targets:
deps:
- grpc++_test_config
- grpc++_test_util
- name: race_test
gtest: true
build: test
language: c++
headers:
- src/core/lib/promise/poll.h
- src/core/lib/promise/race.h
src:
- test/core/promise/race_test.cc
deps:
- absl/types:variant
uses_polling: false
- name: raw_end2end_test
gtest: true
build: test

@ -0,0 +1,80 @@
// 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_RACE_H
#define GRPC_CORE_LIB_PROMISE_RACE_H
#include <grpc/impl/codegen/port_platform.h>
#include <tuple>
#include "src/core/lib/promise/poll.h"
namespace grpc_core {
namespace promise_detail {
// Implementation type for Race combinator.
template <typename... Promises>
class Race;
template <typename Promise, typename... Promises>
class Race<Promise, Promises...> {
public:
using Result = decltype(std::declval<Promise>()());
explicit Race(Promise promise, Promises... promises)
: promise_(std::move(promise)), next_(std::move(promises)...) {}
Result operator()() {
// Check our own promise.
auto r = promise_();
if (absl::holds_alternative<Pending>(r)) {
// Check the rest of them.
return next_();
}
// Return the first ready result.
return std::move(absl::get<kPollReadyIdx>(std::move(r)));
}
private:
// The Promise checked by this instance.
Promise promise_;
// We recursively expand to check the rest of the instances.
Race<Promises...> next_;
};
template <typename Promise>
class Race<Promise> {
public:
using Result = decltype(std::declval<Promise>()());
explicit Race(Promise promise) : promise_(std::move(promise)) {}
Result operator()() { return promise_(); }
private:
Promise promise_;
};
} // namespace promise_detail
/// Run all the promises, return the first result that's available.
/// If two results are simultaneously available, bias towards the first result
/// listed.
template <typename... Promises>
promise_detail::Race<Promises...> Race(Promises... promises) {
return promise_detail::Race<Promises...>(std::move(promises)...);
}
} // namespace grpc_core
#endif // GRPC_CORE_LIB_PROMISE_RACE_H

@ -60,6 +60,18 @@ grpc_cc_test(
],
)
grpc_cc_test(
name = "race_test",
srcs = ["race_test.cc"],
external_deps = ["gtest"],
language = "c++",
uses_polling = False,
deps = [
"//:race",
"//test/core/util:grpc_suppressions",
],
)
grpc_cc_test(
name = "promise_factory_test",
srcs = ["promise_factory_test.cc"],

@ -0,0 +1,32 @@
// 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/race.h"
#include <gtest/gtest.h>
namespace grpc_core {
Poll<int> instant() { return 1; }
Poll<int> never() { return Pending(); }
TEST(RaceTest, Race1) { EXPECT_EQ(Race(instant)(), Poll<int>(1)); }
TEST(RaceTest, Race2A) { EXPECT_EQ(Race(instant, never)(), Poll<int>(1)); }
TEST(RaceTest, Race2B) { EXPECT_EQ(Race(never, instant)(), Poll<int>(1)); }
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -5825,6 +5825,30 @@
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "race_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save