Promise library context management helpers (#26912)

* Promise library context management helpers

* Automated change: Fix sanity tests

* Automated change: Fix sanity tests

* fixes

* Automated change: Fix sanity tests

* missing file

* Automated change: Fix sanity tests

* compatibility

* build

* Automated change: Fix sanity tests

* propagate

* Automated change: Fix sanity tests

* merge with head

* Automated change: Fix sanity tests

Co-authored-by: ctiller <ctiller@users.noreply.github.com>
pull/27073/head
Craig Tiller 3 years ago committed by GitHub
parent 4744aceb68
commit aacd32c721
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      BUILD
  2. 37
      CMakeLists.txt
  3. 2
      Makefile
  4. 13
      build_autogenerated.yaml
  5. 4
      src/core/lib/gpr/tls.h
  6. 84
      src/core/lib/promise/context.h
  7. 12
      test/core/promise/BUILD
  8. 41
      test/core/promise/context_test.cc
  9. 24
      tools/run_tests/generated/tests.json

21
BUILD

@ -665,7 +665,6 @@ grpc_cc_library(
"src/core/lib/gpr/string.h",
"src/core/lib/gpr/string_windows.h",
"src/core/lib/gpr/time_precise.h",
"src/core/lib/gpr/tls.h",
"src/core/lib/gpr/tmpfile.h",
"src/core/lib/gpr/useful.h",
"src/core/lib/gprpp/arena.h",
@ -708,10 +707,17 @@ grpc_cc_library(
"debug_location",
"google_api_upb",
"gpr_codegen",
"gpr_tls",
"grpc_codegen",
],
)
grpc_cc_library(
name = "gpr_tls",
hdrs = ["src/core/lib/gpr/tls.h"],
deps = ["gpr_platform"],
)
grpc_cc_library(
name = "capture",
external_deps = ["absl/utility"],
@ -870,6 +876,18 @@ grpc_cc_library(
deps = ["gpr_platform"],
)
grpc_cc_library(
name = "context",
language = "c++",
public_hdrs = [
"src/core/lib/promise/context.h",
],
deps = [
"gpr_platform",
"gpr_tls",
],
)
grpc_cc_library(
name = "map",
language = "c++",
@ -1350,6 +1368,7 @@ grpc_cc_library(
"dual_ref_counted",
"gpr_base",
"gpr_codegen",
"gpr_tls",
"grpc_codegen",
"grpc_trace",
"orphanable",

37
CMakeLists.txt generated

@ -843,6 +843,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx connectivity_state_test)
add_dependencies(buildtests_cxx context_allocator_end2end_test)
add_dependencies(buildtests_cxx context_list_test)
add_dependencies(buildtests_cxx context_test)
add_dependencies(buildtests_cxx core_configuration_test)
add_dependencies(buildtests_cxx delegating_channel_test)
add_dependencies(buildtests_cxx destroy_grpclb_channel_with_active_connect_stress_test)
@ -2159,7 +2160,6 @@ foreach(_hdr
include/grpc/grpc_posix.h
include/grpc/grpc_security.h
include/grpc/grpc_security_constants.h
include/grpc/impl/codegen/port_platform.h
include/grpc/load_reporting.h
include/grpc/slice.h
include/grpc/slice_buffer.h
@ -2714,7 +2714,6 @@ foreach(_hdr
include/grpc/grpc.h
include/grpc/grpc_posix.h
include/grpc/grpc_security_constants.h
include/grpc/impl/codegen/port_platform.h
include/grpc/load_reporting.h
include/grpc/slice.h
include/grpc/slice_buffer.h
@ -10235,6 +10234,40 @@ target_link_libraries(context_list_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(context_test
test/core/promise/context_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(context_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(context_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
)
endif()
if(gRPC_BUILD_TESTS)

2
Makefile generated

@ -1628,7 +1628,6 @@ PUBLIC_HEADERS_C += \
include/grpc/grpc_posix.h \
include/grpc/grpc_security.h \
include/grpc/grpc_security_constants.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/load_reporting.h \
include/grpc/slice.h \
include/grpc/slice_buffer.h \
@ -2034,7 +2033,6 @@ PUBLIC_HEADERS_C += \
include/grpc/grpc.h \
include/grpc/grpc_posix.h \
include/grpc/grpc_security_constants.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/load_reporting.h \
include/grpc/slice.h \
include/grpc/slice_buffer.h \

@ -416,7 +416,6 @@ libs:
- include/grpc/grpc_posix.h
- include/grpc/grpc_security.h
- include/grpc/grpc_security_constants.h
- include/grpc/impl/codegen/port_platform.h
- include/grpc/load_reporting.h
- include/grpc/slice.h
- include/grpc/slice_buffer.h
@ -1653,7 +1652,6 @@ libs:
- include/grpc/grpc.h
- include/grpc/grpc_posix.h
- include/grpc/grpc_security_constants.h
- include/grpc/impl/codegen/port_platform.h
- include/grpc/load_reporting.h
- include/grpc/slice.h
- include/grpc/slice_buffer.h
@ -5119,6 +5117,17 @@ targets:
deps:
- grpc_test_util
uses_polling: false
- name: context_test
gtest: true
build: test
language: c++
headers:
- src/core/lib/gpr/tls.h
- src/core/lib/promise/context.h
src:
- test/core/promise/context_test.cc
deps: []
uses_polling: false
- name: core_configuration_test
gtest: true
build: test

@ -19,7 +19,7 @@
#ifndef GRPC_CORE_LIB_GPR_TLS_H
#define GRPC_CORE_LIB_GPR_TLS_H
#include <grpc/support/port_platform.h>
#include <grpc/impl/codegen/port_platform.h>
#include <type_traits>
@ -144,7 +144,7 @@ class PthreadTlsImpl : TlsTypeConstrainer<T> {
#else
#define GPR_THREAD_LOCAL(type) \
thread_local grpc_core::TlsTypeConstrainer<type>::Type
thread_local typename grpc_core::TlsTypeConstrainer<type>::Type
#endif

@ -0,0 +1,84 @@
// 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_CONTEXT_H
#define GRPC_CORE_LIB_PROMISE_CONTEXT_H
#include <grpc/impl/codegen/port_platform.h>
#include <utility>
#include "src/core/lib/gpr/tls.h"
namespace grpc_core {
// To avoid accidentally creating context types, we require an explicit
// specialization of this template per context type. The specialization need
// not contain any members, only exist.
// The reason for avoiding this is that context types each use a thread local.
template <typename T>
struct ContextType;
namespace promise_detail {
template <typename T>
class Context : public ContextType<T> {
public:
explicit Context(T* p) : old_(current_) { current_ = p; }
~Context() { current_ = old_; }
Context(const Context&) = delete;
Context& operator=(const Context&) = delete;
static T* get() { return current_; }
private:
T* const old_;
static GPR_THREAD_LOCAL(T*) current_;
};
template <typename T>
GPR_THREAD_LOCAL(T*)
Context<T>::current_;
template <typename T, typename F>
class WithContext {
public:
WithContext(F f, T* context) : context_(context), f_(std::move(f)) {}
decltype(std::declval<F>()()) operator()() {
Context<T> ctx(context_);
return f_();
}
private:
T* context_;
F f_;
};
} // namespace promise_detail
// Retrieve the current value of a context.
template <typename T>
T* GetContext() {
return promise_detail::Context<T>::get();
}
// Given a promise and a context, return a promise that has that context set.
template <typename T, typename F>
promise_detail::WithContext<T, F> WithContext(F f, T* context) {
return promise_detail::WithContext<T, F>(f, context);
}
} // namespace grpc_core
#endif // GRPC_CORE_LIB_PROMISE_CONTEXT_H

@ -30,6 +30,18 @@ grpc_cc_test(
],
)
grpc_cc_test(
name = "context_test",
srcs = ["context_test.cc"],
external_deps = ["gtest"],
language = "c++",
uses_polling = False,
deps = [
"//:context",
"//test/core/util:grpc_suppressions",
],
)
grpc_cc_test(
name = "promise_test",
srcs = ["promise_test.cc"],

@ -0,0 +1,41 @@
// 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/context.h"
#include <gtest/gtest.h>
namespace grpc_core {
struct TestContext {
bool done = false;
};
template <>
struct ContextType<TestContext> {};
TEST(Context, WithContext) {
EXPECT_EQ(GetContext<TestContext>(), nullptr);
TestContext test;
EXPECT_EQ(GetContext<TestContext>(), nullptr);
EXPECT_EQ(test.done, false);
WithContext([]() { GetContext<TestContext>()->done = true; }, &test)();
EXPECT_EQ(test.done, true);
}
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

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

Loading…
Cancel
Save