GRPC-C++源碼分析(三)--ServerCompletionQueue

對應《GRPC-C++源碼分析(二)--main函數主要流程》中的1.1節 初始化ServerCompletionQueue

1 overview

先來看下ServerCompletionQueue的整體結構

GRPC-C++源碼分析(三)--ServerCompletionQueue

ServerCompletionQueue的核心在於創建了grpc_completion_queue* cq_,見其父類CompletionQueue的構造函數

<code>  CompletionQueue(const grpc_completion_queue_attributes& attributes) {
cq_ = g_core_codegen_interface->grpc_completion_queue_create(
g_core_codegen_interface->grpc_completion_queue_factory_lookup(
&attributes),
&attributes, NULL);
InitialAvalanching(); // reserve this for the future shutdown
}/<code>

而CompletionQueue則繼承了GrpcLibraryCodegen。瞭解ServerCompletionQueue類需要我們從頂級父類一層層分析

2 GrpcLibraryCodegen

<code>class GrpcLibraryCodegen {
public:
GrpcLibraryCodegen(bool call_grpc_init = true) : grpc_init_called_(false) {
if (call_grpc_init) {
GPR_CODEGEN_ASSERT(g_glip &&
"gRPC library not initialized. See "
"grpc::internal::GrpcLibraryInitializer.");
g_glip->init();
grpc_init_called_ = true;
}
}/<code>

GrpcLibraryCodegen極為簡單,僅僅調用了g_glip->init();所以重點在g_glip上,讓我們看看它的來源

GRPC-C++源碼分析(三)--ServerCompletionQueue

  • g_glip在GrpcLibraryInitializer類的構造函數中被初始化。
  • grpc聲明瞭一個全局的靜態變量static internal::GrpcLibraryInitializer g_gli_initializer;以確保在main函數之前就完成了g_glip的初始化
<code>class GrpcLibraryInitializer final {
public:
GrpcLibraryInitializer() {
if (grpc::g_glip == nullptr) {
static auto* const g_gli = new GrpcLibrary();
grpc::g_glip = g_gli;
}
if (grpc::g_core_codegen_interface == nullptr) {
static auto* const g_core_codegen = new CoreCodegen();
grpc::g_core_codegen_interface = g_core_codegen;
}
}/<code>
  • 在代碼中可以看到,除了g_glip 外,還有grpc::g_core_codegen_interface也初始化了。這個變量會被用在CompletionQueue的構造函數中,後面會說到
  • 從圖中可以看到g_glip->init方法實際調用的是GrpcLibrary中的init方法
<code>class GrpcLibrary final : public GrpcLibraryInterface {
public:
void init() override { grpc_init(); }
void shutdown() override { grpc_shutdown(); }
};/<code>
  • 重點轉移到了grpc_init()方法中

2.1 grpc_init(init.cc)

顧名思義,grpc_init代表的是初始化grpc核心參數,所以在此方法中,可以看到n多*_init()方法,目前先把注意力放在grpc_iomgr_init();


GRPC-C++源碼分析(三)--ServerCompletionQueue

  • 在grpc_iomgr_init中,開始涉及到grpc/src/core部分的代碼,這是c風格的庫。
  • 這裡決定了後續使用的是哪個系統平臺的reactor模型,epoll還是poll,或者其他
  • 還記得線程模型中的default-executor和resolver-executor麼,它們是由grpc_core::Executor::InitAll方法啟動的
  • grpc_iomgr_platform_init的最終作用是賦值給全局變量:static const grpc_event_engine_vtable* g_event_engine = nullptr;後面的分析會看到


2.1.1 grpc_core::Executor::InitAll

<code>//executor.cc
void Executor::InitAll() {
EXECUTOR_TRACE0("Executor::InitAll() enter");

// Return if Executor::InitAll() is already called earlier
if (executors[static_cast<size>(ExecutorType::DEFAULT)] != nullptr) {
GPR_ASSERT(executors[static_cast<size>(ExecutorType::RESOLVER)] !=
nullptr);
return;
}

executors[static_cast<size>(ExecutorType::DEFAULT)] =
grpc_core::New<executor>("default-executor");
executors[static_cast<size>(ExecutorType::RESOLVER)] =
grpc_core::New<executor>("resolver-executor");

executors[static_cast<size>(ExecutorType::DEFAULT)]->Init();
executors[static_cast<size>(ExecutorType::RESOLVER)]->Init();

EXECUTOR_TRACE0("Executor::InitAll() done");
}/<size>/<size>/<executor>/<size>/<executor>/<size>/<size>/<size>/<code>
  • Init方法中啟動的各自的線程,比較好跟蹤,不再贅述

grpc_determine_iomgr_platform和grpc_iomgr_platform_init方法我們放在下一章統一說明


分享到:


相關文章: