From 3b8f3354de5af07ea595713623bcc19cd19d6dfe Mon Sep 17 00:00:00 2001
From: Yuchen Zeng <zyc@google.com>
Date: Tue, 3 May 2016 12:18:13 -0700
Subject: [PATCH] Add plugins at the time of static initialization

---
 include/grpc++/impl/server_builder_plugin.h   | 10 -------
 include/grpc++/server_builder.h               |  3 ++
 src/cpp/server/server_builder.cc              | 18 ++++++++++++
 .../cpp/end2end/server_builder_plugin_test.cc | 28 ++++++++++++++-----
 4 files changed, 42 insertions(+), 17 deletions(-)

diff --git a/include/grpc++/impl/server_builder_plugin.h b/include/grpc++/impl/server_builder_plugin.h
index 7cf369e346..f792c4b321 100644
--- a/include/grpc++/impl/server_builder_plugin.h
+++ b/include/grpc++/impl/server_builder_plugin.h
@@ -64,16 +64,6 @@ class ServerBuilderPlugin {
 
 }  // namespace grpc
 
-#define GRPC_DECLARE_PLUGIN(plugin_name)                               \
-  namespace sBP##plugin_name {                                         \
-    extern std::unique_ptr<ServerBuilderPlugin> Create##plugin_name(); \
-  }
 
-#define GRPC_INIT_PLUGIN(map, plugin_name)        \
-  {                                               \
-    std::unique_ptr<ServerBuilderPlugin> plugin = \
-        sBP##plugin_name::Create##plugin_name();  \
-    map[plugin->name()] = std::move(plugin);      \
-  }
 
 #endif  // GRPCXX_IMPL_SERVER_BUILDER_PLUGIN_H
diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h
index a47b5c71cf..52064b1434 100644
--- a/include/grpc++/server_builder.h
+++ b/include/grpc++/server_builder.h
@@ -113,6 +113,9 @@ class ServerBuilder {
   /// Return a running server which is ready for processing calls.
   std::unique_ptr<Server> BuildAndStart();
 
+  static void InternalAddPluginFactory(
+      std::unique_ptr<ServerBuilderPlugin> (*CreatePlugin)());
+
  private:
   friend class ::grpc::testing::ServerBuilderPluginTest;
 
diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc
index 5dc73ed1e4..b6e48efa8d 100644
--- a/src/cpp/server/server_builder.cc
+++ b/src/cpp/server/server_builder.cc
@@ -41,9 +41,21 @@
 
 namespace grpc {
 
+static std::vector<std::unique_ptr<ServerBuilderPlugin> (*)()>* plugin_list;
+static gpr_once once_init_plugin_list = GPR_ONCE_INIT;
+
+static void do_plugin_list_init(void) {
+  plugin_list = new std::vector<std::unique_ptr<ServerBuilderPlugin> (*)()>();
+}
+
 ServerBuilder::ServerBuilder()
     : max_message_size_(-1), generic_service_(nullptr) {
   grpc_compression_options_init(&compression_options_);
+  gpr_once_init(&once_init_plugin_list, do_plugin_list_init);
+  for (auto factory : (*plugin_list)) {
+    std::unique_ptr<ServerBuilderPlugin> plugin = factory();
+    plugins_[plugin->name()] = std::move(plugin);
+  }
 }
 
 std::unique_ptr<ServerCompletionQueue> ServerBuilder::AddCompletionQueue() {
@@ -156,4 +168,10 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
   return server;
 }
 
+void ServerBuilder::InternalAddPluginFactory(
+    std::unique_ptr<ServerBuilderPlugin> (*CreatePlugin)()) {
+  gpr_once_init(&once_init_plugin_list, do_plugin_list_init);
+  (*plugin_list).push_back(CreatePlugin);
+}
+
 }  // namespace grpc
diff --git a/test/cpp/end2end/server_builder_plugin_test.cc b/test/cpp/end2end/server_builder_plugin_test.cc
index 9ed176d29d..0d44999a08 100644
--- a/test/cpp/end2end/server_builder_plugin_test.cc
+++ b/test/cpp/end2end/server_builder_plugin_test.cc
@@ -115,6 +115,11 @@ class InsertPluginServerBuilderOption : public ServerBuilderOption {
   void UpdatePlugins(
       std::map<grpc::string, std::unique_ptr<ServerBuilderPlugin>>* plugins)
       GRPC_OVERRIDE {
+    auto it = plugins->begin();
+    while (it != plugins->end()) {
+      plugins->erase(it++);
+    }
+
     std::unique_ptr<TestServerBuilderPlugin> plugin(
         new TestServerBuilderPlugin());
     if (register_service_) plugin->SetRegisterService();
@@ -127,13 +132,24 @@ class InsertPluginServerBuilderOption : public ServerBuilderOption {
   bool register_service_;
 };
 
-namespace sBPTestServerBuilderPlugin {
-
 std::unique_ptr<ServerBuilderPlugin> CreateTestServerBuilderPlugin() {
   return std::unique_ptr<ServerBuilderPlugin>(new TestServerBuilderPlugin());
 }
 
-}  // namespace sBPTestServerBuilderPlugin
+void grpc_AddServerBuilderPlugin_reflection() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  ::grpc::ServerBuilder::InternalAddPluginFactory(
+      &CreateTestServerBuilderPlugin);
+}
+
+// Force AddServerBuilderPlugin() to be called at static initialization time.
+struct StaticPluginInitializer_reflection {
+  StaticPluginInitializer_reflection() {
+    grpc_AddServerBuilderPlugin_reflection();
+  }
+} static_plugin_initializer_reflection_;
 
 class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> {
  public:
@@ -146,8 +162,7 @@ class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> {
 
   void InsertPlugin() {
     if (GetParam()) {
-      // Add ServerBuilder plugin directly
-      GRPC_INIT_PLUGIN(builder_->plugins_, TestServerBuilderPlugin);
+      // Add ServerBuilder plugin in static initialization
       EXPECT_TRUE(builder_->plugins_[PLUGIN_NAME] != nullptr);
     } else {
       // Add ServerBuilder plugin using ServerBuilder::SetOption()
@@ -158,8 +173,7 @@ class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> {
 
   void InsertPluginWithTestService() {
     if (GetParam()) {
-      // Add ServerBuilder plugin directly
-      GRPC_INIT_PLUGIN(builder_->plugins_, TestServerBuilderPlugin);
+      // Add ServerBuilder plugin in static initialization
       EXPECT_TRUE(builder_->plugins_[PLUGIN_NAME] != nullptr);
       auto plugin = static_cast<TestServerBuilderPlugin*>(
           builder_->plugins_[PLUGIN_NAME].get());
-- 
GitLab