简体   繁体   English

grpc c++ 异步完成队列事件

[英]grpc c++ async completion queue events

I am trying to understand the grpc c++ async model flow.我试图了解 grpc c++ 异步 model 流程。 This article ( link ) already explains many of my doubts.这篇文章( 链接)已经解释了我的许多疑惑。 Here is the code for grpc_asycn_server .这是grpc_asycn_server的代码。 To understand when CompletionQueue is getting requests, I added a few print statements as follows:为了了解 CompletionQueue 何时收到请求,我添加了一些打印语句,如下所示:

First inside the HandleRpcs() function.首先在 HandleRpcs() function 中。

void HandleRpcs() {
    // Spawn a new CallData instance to serve new clients.
    new CallData(&service_, cq_.get());
    void* tag;  // uniquely identifies a request.
    bool ok;
    int i = 0;
    while (true) {
      std::cout << i << std::endl; ///////////////////////////////
      // Block waiting to read the next event from the completion queue. The
      // event is uniquely identified by its tag, which in this case is the
      // memory address of a CallData instance.
      // The return value of Next should always be checked. This return value
      // tells us whether there is any kind of event or cq_ is shutting down.
      GPR_ASSERT(cq_->Next(&tag, &ok));
      GPR_ASSERT(ok);
      static_cast<CallData*>(tag)->Proceed();
      i++;
    }
  }

and inside the proceed() function:在proceed() function中:

void Proceed() {
  if (status_ == CREATE) {
    // Make this instance progress to the PROCESS state.
    status_ = PROCESS;

    // As part of the initial CREATE state, we *request* that the system
    // start processing SayHello requests. In this request, "this" acts are
    // the tag uniquely identifying the request (so that different CallData
    // instances can serve different requests concurrently), in this case
    // the memory address of this CallData instance.
    std::cout<<"RequestSayHello called"<<std::endl; ////////////////////////////
    service_->RequestSayHello(&ctx_, &request_, &responder_, cq_, cq_,
                              this);
  } else if (status_ == PROCESS) {
    // Spawn a new CallData instance to serve new clients while we process
    // the one for this CallData. The instance will deallocate itself as
    // part of its FINISH state.
    new CallData(service_, cq_);

    // The actual processing.
    std::string prefix("Hello ");
    reply_.set_message(prefix + request_.name());

    // And we are done! Let the gRPC runtime know we've finished, using the
    // memory address of this instance as the uniquely identifying tag for
    // the event.
    status_ = FINISH;
    responder_.Finish(reply_, Status::OK, this);
  } else {
    std::cout<<"deallocated"<<std::endl; ////////////////////////////
    GPR_ASSERT(status_ == FINISH);
    // Once in the FINISH state, deallocate ourselves (CallData).
    delete this;
  }
}

Once I run the server and the one client ( client ) then the server prints the following:一旦我运行服务器和一个客户端( 客户端),服务器就会打印以下内容:

RequestSayHello called
i = 0
RequestSayHello called
i = 1
deallocated
i = 2

The second RequestSayHello called makes sense because of the creation of new CallData instance.由于创建了新的CallData实例,调用的第二个RequestSayHello called是有意义的。 My question is how come proceed() function executed the second time and deallocated gets printed?我的问题是如何proceed() function 第二次执行并deallocated被打印?

The completion queue ( cq_ ) structure handles several types of events, including both request and response events.完成队列 ( cq_ ) 结构处理多种类型的事件,包括请求响应事件。 The first call to proceed() enters the PROCESS stage of the state machine for the CallData object.proceed()的第一次调用进入PROCESS机器的处理阶段,用于CallData object。

During this stage:在此阶段:
1. A new CallData object is created; 1、新建CallData object; this inserts a request event into cq_ as you mentioned如您所述,这会将请求事件插入cq_
2. The responder_ is called with the reply object; 2. responder_ _被调用,回复为object; this inserts a response event into cq_这会将响应事件插入cq_

Upon receiving the response event from cq_ , proceed() is called again on the first CallData object, which is now in the FINISH state, so clean up is performed and deallocated is printed.在收到来自cq_的响应事件后,在第一个CallData object 上再次调用proceed() ,它现在位于FINISH state 中,因此执行清理并打印deallocated

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM