Revert "Arena allocated promise (#28023)" (#28171)

This reverts commit 77b4ade1a7.
pull/28176/head
Craig Tiller 3 years ago committed by GitHub
parent aac5af4cde
commit 9b07a81b1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      BUILD
  2. 103
      CMakeLists.txt
  3. 119
      build_autogenerated.yaml
  4. 181
      src/core/lib/promise/arena_promise.h
  5. 12
      test/core/promise/BUILD
  6. 45
      test/core/promise/arena_promise_test.cc
  7. 24
      tools/run_tests/generated/tests.json

15
BUILD

@ -1090,21 +1090,6 @@ grpc_cc_library(
], ],
) )
grpc_cc_library(
name = "arena_promise",
external_deps = [
"absl/types:optional",
],
language = "c++",
public_hdrs = [
"src/core/lib/promise/arena_promise.h",
],
deps = [
"gpr_base",
"poll",
],
)
grpc_cc_library( grpc_cc_library(
name = "promise_like", name = "promise_like",
language = "c++", language = "c++",

103
CMakeLists.txt generated

@ -743,7 +743,6 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx alts_concurrent_connectivity_test) add_dependencies(buildtests_cxx alts_concurrent_connectivity_test)
endif() endif()
add_dependencies(buildtests_cxx alts_util_test) add_dependencies(buildtests_cxx alts_util_test)
add_dependencies(buildtests_cxx arena_promise_test)
add_dependencies(buildtests_cxx async_end2end_test) add_dependencies(buildtests_cxx async_end2end_test)
add_dependencies(buildtests_cxx auth_property_iterator_test) add_dependencies(buildtests_cxx auth_property_iterator_test)
add_dependencies(buildtests_cxx authorization_matchers_test) add_dependencies(buildtests_cxx authorization_matchers_test)
@ -7855,108 +7854,6 @@ target_link_libraries(alts_util_test
) )
endif()
if(gRPC_BUILD_TESTS)
add_executable(arena_promise_test
src/core/ext/upb-generated/google/api/annotations.upb.c
src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c
src/core/ext/upb-generated/google/api/http.upb.c
src/core/ext/upb-generated/google/protobuf/any.upb.c
src/core/ext/upb-generated/google/protobuf/duration.upb.c
src/core/ext/upb-generated/google/protobuf/empty.upb.c
src/core/ext/upb-generated/google/protobuf/struct.upb.c
src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
src/core/ext/upb-generated/google/rpc/status.upb.c
src/core/lib/gpr/alloc.cc
src/core/lib/gpr/atm.cc
src/core/lib/gpr/cpu_iphone.cc
src/core/lib/gpr/cpu_linux.cc
src/core/lib/gpr/cpu_posix.cc
src/core/lib/gpr/cpu_windows.cc
src/core/lib/gpr/env_linux.cc
src/core/lib/gpr/env_posix.cc
src/core/lib/gpr/env_windows.cc
src/core/lib/gpr/log.cc
src/core/lib/gpr/log_android.cc
src/core/lib/gpr/log_linux.cc
src/core/lib/gpr/log_posix.cc
src/core/lib/gpr/log_windows.cc
src/core/lib/gpr/murmur_hash.cc
src/core/lib/gpr/string.cc
src/core/lib/gpr/string_posix.cc
src/core/lib/gpr/string_util_windows.cc
src/core/lib/gpr/string_windows.cc
src/core/lib/gpr/sync.cc
src/core/lib/gpr/sync_abseil.cc
src/core/lib/gpr/sync_posix.cc
src/core/lib/gpr/sync_windows.cc
src/core/lib/gpr/time.cc
src/core/lib/gpr/time_posix.cc
src/core/lib/gpr/time_precise.cc
src/core/lib/gpr/time_windows.cc
src/core/lib/gpr/tmpfile_msys.cc
src/core/lib/gpr/tmpfile_posix.cc
src/core/lib/gpr/tmpfile_windows.cc
src/core/lib/gpr/wrap_memcpy.cc
src/core/lib/gprpp/arena.cc
src/core/lib/gprpp/examine_stack.cc
src/core/lib/gprpp/fork.cc
src/core/lib/gprpp/global_config_env.cc
src/core/lib/gprpp/host_port.cc
src/core/lib/gprpp/mpscq.cc
src/core/lib/gprpp/stat_posix.cc
src/core/lib/gprpp/stat_windows.cc
src/core/lib/gprpp/status_helper.cc
src/core/lib/gprpp/thd_posix.cc
src/core/lib/gprpp/thd_windows.cc
src/core/lib/gprpp/time_util.cc
src/core/lib/profiling/basic_timers.cc
src/core/lib/profiling/stap_timers.cc
test/core/promise/arena_promise_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(arena_promise_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(arena_promise_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::base
absl::core_headers
absl::memory
absl::status
absl::cord
absl::str_format
absl::strings
absl::synchronization
absl::time
absl::optional
absl::variant
upb
)
endif() endif()
if(gRPC_BUILD_TESTS) if(gRPC_BUILD_TESTS)

@ -4535,125 +4535,6 @@ targets:
deps: deps:
- grpc++_alts - grpc++_alts
- grpc++_test_util - grpc++_test_util
- name: arena_promise_test
gtest: true
build: test
language: c++
headers:
- src/core/ext/upb-generated/google/api/annotations.upb.h
- src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.h
- src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.h
- src/core/ext/upb-generated/google/api/http.upb.h
- src/core/ext/upb-generated/google/protobuf/any.upb.h
- src/core/ext/upb-generated/google/protobuf/duration.upb.h
- src/core/ext/upb-generated/google/protobuf/empty.upb.h
- src/core/ext/upb-generated/google/protobuf/struct.upb.h
- src/core/ext/upb-generated/google/protobuf/timestamp.upb.h
- src/core/ext/upb-generated/google/protobuf/wrappers.upb.h
- src/core/ext/upb-generated/google/rpc/status.upb.h
- src/core/lib/gpr/alloc.h
- src/core/lib/gpr/env.h
- src/core/lib/gpr/murmur_hash.h
- src/core/lib/gpr/spinlock.h
- 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
- src/core/lib/gprpp/construct_destruct.h
- src/core/lib/gprpp/debug_location.h
- src/core/lib/gprpp/examine_stack.h
- src/core/lib/gprpp/fork.h
- src/core/lib/gprpp/global_config.h
- src/core/lib/gprpp/global_config_custom.h
- src/core/lib/gprpp/global_config_env.h
- src/core/lib/gprpp/global_config_generic.h
- src/core/lib/gprpp/host_port.h
- src/core/lib/gprpp/manual_constructor.h
- src/core/lib/gprpp/memory.h
- src/core/lib/gprpp/mpscq.h
- src/core/lib/gprpp/stat.h
- src/core/lib/gprpp/status_helper.h
- src/core/lib/gprpp/sync.h
- src/core/lib/gprpp/thd.h
- src/core/lib/gprpp/time_util.h
- src/core/lib/profiling/timers.h
- src/core/lib/promise/arena_promise.h
- src/core/lib/promise/poll.h
src:
- src/core/ext/upb-generated/google/api/annotations.upb.c
- src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c
- src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c
- src/core/ext/upb-generated/google/api/http.upb.c
- src/core/ext/upb-generated/google/protobuf/any.upb.c
- src/core/ext/upb-generated/google/protobuf/duration.upb.c
- src/core/ext/upb-generated/google/protobuf/empty.upb.c
- src/core/ext/upb-generated/google/protobuf/struct.upb.c
- src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
- src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
- src/core/ext/upb-generated/google/rpc/status.upb.c
- src/core/lib/gpr/alloc.cc
- src/core/lib/gpr/atm.cc
- src/core/lib/gpr/cpu_iphone.cc
- src/core/lib/gpr/cpu_linux.cc
- src/core/lib/gpr/cpu_posix.cc
- src/core/lib/gpr/cpu_windows.cc
- src/core/lib/gpr/env_linux.cc
- src/core/lib/gpr/env_posix.cc
- src/core/lib/gpr/env_windows.cc
- src/core/lib/gpr/log.cc
- src/core/lib/gpr/log_android.cc
- src/core/lib/gpr/log_linux.cc
- src/core/lib/gpr/log_posix.cc
- src/core/lib/gpr/log_windows.cc
- src/core/lib/gpr/murmur_hash.cc
- src/core/lib/gpr/string.cc
- src/core/lib/gpr/string_posix.cc
- src/core/lib/gpr/string_util_windows.cc
- src/core/lib/gpr/string_windows.cc
- src/core/lib/gpr/sync.cc
- src/core/lib/gpr/sync_abseil.cc
- src/core/lib/gpr/sync_posix.cc
- src/core/lib/gpr/sync_windows.cc
- src/core/lib/gpr/time.cc
- src/core/lib/gpr/time_posix.cc
- src/core/lib/gpr/time_precise.cc
- src/core/lib/gpr/time_windows.cc
- src/core/lib/gpr/tmpfile_msys.cc
- src/core/lib/gpr/tmpfile_posix.cc
- src/core/lib/gpr/tmpfile_windows.cc
- src/core/lib/gpr/wrap_memcpy.cc
- src/core/lib/gprpp/arena.cc
- src/core/lib/gprpp/examine_stack.cc
- src/core/lib/gprpp/fork.cc
- src/core/lib/gprpp/global_config_env.cc
- src/core/lib/gprpp/host_port.cc
- src/core/lib/gprpp/mpscq.cc
- src/core/lib/gprpp/stat_posix.cc
- src/core/lib/gprpp/stat_windows.cc
- src/core/lib/gprpp/status_helper.cc
- src/core/lib/gprpp/thd_posix.cc
- src/core/lib/gprpp/thd_windows.cc
- src/core/lib/gprpp/time_util.cc
- src/core/lib/profiling/basic_timers.cc
- src/core/lib/profiling/stap_timers.cc
- test/core/promise/arena_promise_test.cc
deps:
- absl/base:base
- absl/base:core_headers
- absl/memory:memory
- absl/status:status
- absl/strings:cord
- absl/strings:str_format
- absl/strings:strings
- absl/synchronization:synchronization
- absl/time:time
- absl/types:optional
- absl/types:variant
- upb
uses_polling: false
- name: async_end2end_test - name: async_end2end_test
gtest: true gtest: true
build: test build: test

@ -1,181 +0,0 @@
// 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_ARENA_PROMISE_H
#define GRPC_CORE_LIB_PROMISE_ARENA_PROMISE_H
#include <grpc/support/port_platform.h>
#include <grpc/support/log.h>
#include "src/core/lib/gprpp/arena.h"
#include "src/core/lib/promise/poll.h"
namespace grpc_core {
namespace arena_promise_detail {
// Type erased promise stored in the arena.
template <typename T>
class ImplInterface {
public:
// Poll the promise, once.
virtual Poll<T> PollOnce() = 0;
// Destroy the underlying callable object if there is one.
// Since we don't delete (the arena owns the memory) but we may need to call a
// destructor, we expose this for when the ArenaPromise object is destroyed.
virtual void Destroy() = 0;
protected:
~ImplInterface() = default;
};
// Implementation of ImplInterface for an empty object.
// Used when an empty ArenaPromise is created, or when the ArenaPromise is moved
// from. Since in either case these objects should not be polled, we simply
// crash if it is.
template <typename T>
class NullImpl final : public ImplInterface<T> {
public:
Poll<T> PollOnce() override {
abort();
GPR_UNREACHABLE_CODE(return Pending{});
}
void Destroy() override {}
static ImplInterface<T>* Get() {
static NullImpl<T> instance;
return &instance;
}
private:
~NullImpl() = default;
};
// Implementation of ImplInterface for a callable object.
template <typename T, typename Callable>
class CallableImpl final : public ImplInterface<T> {
public:
explicit CallableImpl(Callable&& callable) : callable_(std::move(callable)) {}
// Forward polls to the callable object.
Poll<T> PollOnce() override { return callable_(); }
// Destroy destructs the callable object.
void Destroy() override { this->~CallableImpl(); }
private:
// Should only be called by Destroy().
~CallableImpl() = default;
Callable callable_;
};
// If a callable object is empty we can substitute any instance of that callable
// for the one we call (for how could we tell the difference)?
// Since this corresponds to a lambda with no fields, and we expect these to be
// reasonably common, we can elide the arena allocation entirely and simply poll
// a global shared instance.
// (this comes up often when the promise only accesses context data from the
// containing activity).
template <typename T, typename Callable>
class SharedImpl final : public ImplInterface<T> {
public:
// Call the callable. Since it's empty it can't access any member variables,
// and as such we can choose any address for the object.
Poll<T> PollOnce() override { return (*static_cast<Callable*>(nullptr))(); }
// Nothing to destroy.
void Destroy() override {}
// Return a pointer to the shared instance - these are singletons, and are
// needed just to get the vtable in place.
static SharedImpl* Get() {
static SharedImpl impl;
return &impl;
}
private:
SharedImpl() = default;
~SharedImpl() = default;
};
// Redirector type: given a callable type, expose a Make() function that creates
// the appropriate underlying implementation.
template <typename T, typename Callable, typename Ignored = void>
struct ChooseImplForCallable;
template <typename T, typename Callable>
struct ChooseImplForCallable<
T, Callable, absl::enable_if_t<!std::is_empty<Callable>::value>> {
static ImplInterface<T>* Make(Arena* arena, Callable&& callable) {
return arena->template New<CallableImpl<T, Callable>>(
std::forward<Callable>(callable));
}
};
template <typename T, typename Callable>
struct ChooseImplForCallable<
T, Callable, absl::enable_if_t<std::is_empty<Callable>::value>> {
static ImplInterface<T>* Make(Arena*, Callable&&) {
return SharedImpl<T, Callable>::Get();
}
};
// Wrap ChooseImplForCallable with a friend approachable syntax.
template <typename T, typename Callable>
ImplInterface<T>* MakeImplForCallable(Arena* arena, Callable&& callable) {
return ChooseImplForCallable<T, Callable>::Make(
arena, std::forward<Callable>(callable));
}
} // namespace arena_promise_detail
// A promise for which the state memory is allocated from an arena.
template <typename T>
class ArenaPromise {
public:
// Construct an empty, uncallable, invalid ArenaPromise.
ArenaPromise() = default;
// Construct an ArenaPromise that will call the given callable when polled.
template <typename Callable>
ArenaPromise(Arena* arena, Callable&& callable)
: impl_(arena_promise_detail::MakeImplForCallable<T>(
arena, std::forward<Callable>(callable))) {}
// ArenaPromise is not copyable.
ArenaPromise(const ArenaPromise&) = delete;
ArenaPromise& operator=(const ArenaPromise&) = delete;
// ArenaPromise is movable.
ArenaPromise(ArenaPromise&& other) noexcept : impl_(other.impl_) {
other.impl_ = arena_promise_detail::NullImpl<T>::Get();
}
ArenaPromise& operator=(ArenaPromise&& other) noexcept {
impl_ = other.impl_;
other.impl_ = arena_promise_detail::NullImpl<T>::Get();
return *this;
}
// Destruction => call Destroy on the underlying impl object.
~ArenaPromise() { impl_->Destroy(); }
// Expose the promise interface: a call operator that returns Poll<T>.
Poll<T> operator()() { return impl_->PollOnce(); }
private:
// Underlying impl object.
arena_promise_detail::ImplInterface<T>* impl_ =
arena_promise_detail::NullImpl<T>::Get();
};
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_PROMISE_ARENA_PROMISE_H */

@ -67,18 +67,6 @@ grpc_cc_test(
], ],
) )
grpc_cc_test(
name = "arena_promise_test",
srcs = ["arena_promise_test.cc"],
external_deps = ["gtest"],
language = "c++",
uses_polling = False,
deps = [
"//:arena_promise",
"//test/core/util:grpc_suppressions",
],
)
grpc_cc_test( grpc_cc_test(
# Why promise_map_test and not map_test? # Why promise_map_test and not map_test?
# third_party/benchmark defines a map_test in its cmakefile, and we depend # third_party/benchmark defines a map_test in its cmakefile, and we depend

@ -1,45 +0,0 @@
// 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/arena_promise.h"
#include <memory>
#include <gtest/gtest.h>
namespace grpc_core {
TEST(ArenaPromiseTest, AllocatedWorks) {
auto arena = MakeScopedArena(1024);
int x = 42;
ArenaPromise<int> p(arena.get(), [x] { return Poll<int>(x); });
EXPECT_EQ(p(), Poll<int>(42));
p = ArenaPromise<int>(arena.get(), [] { return Poll<int>(43); });
EXPECT_EQ(p(), Poll<int>(43));
}
TEST(ArenaPromiseTest, DestructionWorks) {
auto arena = MakeScopedArena(1024);
auto x = std::make_shared<int>(42);
auto p = ArenaPromise<int>(arena.get(), [x] { return Poll<int>(*x); });
ArenaPromise<int> q(std::move(p));
EXPECT_EQ(q(), Poll<int>(42));
}
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

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

Loading…
Cancel
Save