Construct DefaultReactor lazily since not always needed

pull/21774/head
Vijay Pai 5 years ago
parent 380b70d3a6
commit 1f0cdd5aad
  1. 19
      include/grpcpp/impl/codegen/server_context_impl.h
  2. 7
      include/grpcpp/test/default_reactor_test_peer.h
  3. 3
      src/cpp/server/server_context.cc

@ -20,8 +20,10 @@
#define GRPCPP_IMPL_CODEGEN_SERVER_CONTEXT_IMPL_H #define GRPCPP_IMPL_CODEGEN_SERVER_CONTEXT_IMPL_H
#include <atomic> #include <atomic>
#include <cassert>
#include <map> #include <map>
#include <memory> #include <memory>
#include <type_traits>
#include <vector> #include <vector>
#include <grpc/impl/codegen/port_platform.h> #include <grpc/impl/codegen/port_platform.h>
@ -301,8 +303,18 @@ class ServerContextBase {
/// ///
/// WARNING: This is experimental API and could be changed or removed. /// WARNING: This is experimental API and could be changed or removed.
::grpc_impl::ServerUnaryReactor* DefaultReactor() { ::grpc_impl::ServerUnaryReactor* DefaultReactor() {
auto reactor = &default_reactor_; Reactor* reactor = reinterpret_cast<Reactor*>(&default_reactor_);
if (test_unary_ != nullptr) {
return reactor;
}
new (reactor) Reactor;
#ifndef NDEBUG
bool old = false;
assert(default_reactor_used_.compare_exchange_strong(
old, true, std::memory_order_relaxed));
#else
default_reactor_used_.store(true, std::memory_order_relaxed); default_reactor_used_.store(true, std::memory_order_relaxed);
#endif
return reactor; return reactor;
} }
@ -445,7 +457,7 @@ class ServerContextBase {
public: public:
TestServerCallbackUnary(ServerContextBase* ctx, TestServerCallbackUnary(ServerContextBase* ctx,
std::function<void(::grpc::Status)> func) std::function<void(::grpc::Status)> func)
: reactor_(&ctx->default_reactor_), func_(std::move(func)) { : reactor_(ctx->DefaultReactor()), func_(std::move(func)) {
this->BindReactor(reactor_); this->BindReactor(reactor_);
} }
void Finish(::grpc::Status s) override { void Finish(::grpc::Status s) override {
@ -472,7 +484,8 @@ class ServerContextBase {
const std::function<void(::grpc::Status s)> func_; const std::function<void(::grpc::Status s)> func_;
}; };
Reactor default_reactor_; typename std::aligned_storage<sizeof(Reactor), alignof(Reactor)>::type
default_reactor_;
std::atomic_bool default_reactor_used_{false}; std::atomic_bool default_reactor_used_{false};
std::unique_ptr<TestServerCallbackUnary> test_unary_; std::unique_ptr<TestServerCallbackUnary> test_unary_;
}; };

@ -29,7 +29,9 @@ namespace testing {
/// DefaultReactor. It is intended for allow unit-testing of a callback API /// DefaultReactor. It is intended for allow unit-testing of a callback API
/// service via direct invocation of the service methods rather than through /// service via direct invocation of the service methods rather than through
/// RPCs. It is only applicable for unary RPC methods that use the /// RPCs. It is only applicable for unary RPC methods that use the
/// DefaultReactor rather than any user-defined reactor. /// DefaultReactor rather than any user-defined reactor. If it is used, it must
/// be created before the RPC is invoked so that it can bind the reactor into a
/// test mode rather than letting it follow the normal paths.
class DefaultReactorTestPeer { class DefaultReactorTestPeer {
public: public:
explicit DefaultReactorTestPeer(experimental::CallbackServerContext* ctx) explicit DefaultReactorTestPeer(experimental::CallbackServerContext* ctx)
@ -40,7 +42,8 @@ class DefaultReactorTestPeer {
ctx->SetupTestDefaultReactor(std::move(finish_func)); ctx->SetupTestDefaultReactor(std::move(finish_func));
} }
::grpc::experimental::ServerUnaryReactor* reactor() const { ::grpc::experimental::ServerUnaryReactor* reactor() const {
return &ctx_->default_reactor_; return reinterpret_cast<experimental::ServerUnaryReactor*>(
&ctx_->default_reactor_);
} }
bool test_status_set() const { return ctx_->test_status_set(); } bool test_status_set() const { return ctx_->test_status_set(); }
Status test_status() const { return ctx_->test_status(); } Status test_status() const { return ctx_->test_status(); }

@ -272,8 +272,7 @@ void ServerContextBase::Clear() {
grpc_call_unref(call); grpc_call_unref(call);
} }
if (default_reactor_used_.load(std::memory_order_relaxed)) { if (default_reactor_used_.load(std::memory_order_relaxed)) {
default_reactor_.~Reactor(); reinterpret_cast<Reactor*>(&default_reactor_)->~Reactor();
new (&default_reactor_) Reactor;
default_reactor_used_.store(false, std::memory_order_relaxed); default_reactor_used_.store(false, std::memory_order_relaxed);
} }
test_unary_.reset(); test_unary_.reset();

Loading…
Cancel
Save