Promise map operator (#26917)

* Poll type for promises library

* Library to talk about things that look like promises if you squint

* Promise helpers, and basic type erasure

* Promise map operator - change return type via a function

* build

* Changes to sync required for promise activities

* sanitized

* Automated change: Fix sanity tests

* fixes

* fixes

* Automated change: Fix sanity tests

* fix build

* review feedback

* Automated change: Fix sanity tests

* comment

Co-authored-by: ctiller <ctiller@users.noreply.github.com>
pull/27022/head
Craig Tiller 4 years ago committed by GitHub
parent 588df691b0
commit 8ed20ae479
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      BUILD
  2. 37
      CMakeLists.txt
  3. 15
      build_autogenerated.yaml
  4. 64
      src/core/lib/promise/map.h
  5. 18
      test/core/promise/BUILD
  6. 31
      test/core/promise/map_test.cc
  7. 24
      tools/run_tests/generated/tests.json

11
BUILD

@ -856,6 +856,17 @@ grpc_cc_library(
deps = ["gpr_platform"],
)
grpc_cc_library(
name = "map",
language = "c++",
public_hdrs = ["src/core/lib/promise/map.h"],
deps = [
"gpr_platform",
"poll",
"promise_like",
],
)
grpc_cc_library(
name = "promise",
external_deps = [

37
CMakeLists.txt generated

@ -916,6 +916,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx popularity_count_test)
add_dependencies(buildtests_cxx port_sharing_end2end_test)
add_dependencies(buildtests_cxx promise_factory_test)
add_dependencies(buildtests_cxx promise_map_test)
add_dependencies(buildtests_cxx promise_test)
add_dependencies(buildtests_cxx proto_server_reflection_test)
add_dependencies(buildtests_cxx proto_utils_test)
@ -13048,6 +13049,42 @@ target_link_libraries(promise_factory_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(promise_map_test
test/core/promise/map_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(promise_map_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(promise_map_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::optional
absl::variant
)
endif()
if(gRPC_BUILD_TESTS)

@ -6077,6 +6077,21 @@ targets:
- absl/types:variant
- absl/utility:utility
uses_polling: false
- name: promise_map_test
gtest: true
build: test
language: c++
headers:
- src/core/lib/promise/detail/promise_like.h
- src/core/lib/promise/map.h
- src/core/lib/promise/poll.h
- src/core/lib/promise/promise.h
src:
- test/core/promise/map_test.cc
deps:
- absl/types:optional
- absl/types:variant
uses_polling: false
- name: promise_test
gtest: true
build: test

@ -0,0 +1,64 @@
// 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_MAP_H
#define GRPC_CORE_LIB_PROMISE_MAP_H
#include <grpc/impl/codegen/port_platform.h>
#include "absl/types/variant.h"
#include "src/core/lib/promise/detail/promise_like.h"
#include "src/core/lib/promise/poll.h"
namespace grpc_core {
namespace promise_detail {
// Implementation of mapping combinator - use this via the free function below!
// Promise is the type of promise to poll on, Fn is a function that takes the
// result of Promise and maps it to some new type.
template <typename Promise, typename Fn>
class Map {
public:
Map(Promise promise, Fn fn)
: promise_(std::move(promise)), fn_(std::move(fn)) {}
using Result = typename PromiseLike<Promise>::Result;
Poll<Result> operator()() {
Poll<Result> r = promise_();
if (auto* p = absl::get_if<kPollReadyIdx>(&r)) {
return fn_(std::move(*p));
}
return Pending();
}
private:
PromiseLike<Promise> promise_;
Fn fn_;
};
} // namespace promise_detail
// Mapping combinator.
// Takes a promise, and a synchronous function to mutate its result, and
// returns a promise.
template <typename Promise, typename Fn>
promise_detail::Map<Promise, Fn> Map(Promise promise, Fn fn) {
return promise_detail::Map<Promise, Fn>(std::move(promise), std::move(fn));
}
} // namespace grpc_core
#endif // GRPC_CORE_LIB_PROMISE_MAP_H

@ -42,6 +42,24 @@ grpc_cc_test(
],
)
grpc_cc_test(
# Why promise_map_test and not map_test?
# third_party/benchmark defines a map_test in its cmakefile, and we depend
# on that from our cmakefile, and cmake wants to have a flat namespace to
# deal with xcode/visual studio limitations... sooo... promise_map_test it
# is.
name = "promise_map_test",
srcs = ["map_test.cc"],
external_deps = ["gtest"],
language = "c++",
uses_polling = False,
deps = [
"//:map",
"//:promise",
"//test/core/util:grpc_suppressions",
],
)
grpc_cc_test(
name = "promise_factory_test",
srcs = ["promise_factory_test.cc"],

@ -0,0 +1,31 @@
// 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/map.h"
#include <gtest/gtest.h>
#include "src/core/lib/promise/promise.h"
namespace grpc_core {
TEST(MapTest, Works) {
Promise<int> x = Map([]() { return 42; }, [](int i) { return i / 2; });
EXPECT_EQ(x(), Poll<int>(21));
}
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -5681,6 +5681,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": "promise_map_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save