如何正确异步使用grpc(ClientAsyncReaderWriter)

How to correctly use grpc asynchronously (ClientAsyncReaderWriter)

本文关键字:ClientAsyncReaderWriter grpc 何正确 异步      更新时间:2023-10-16

我找不到显示如何使用ClientAsyncReaderWriter的grpc示例(有吗?)。我自己尝试了一些东西,但在引用计数方面遇到了问题。我的问题来自于对代码的追踪。

CCD_ 1具有被称为CCD_ 3的CCD_。ClientContext C++对象包装grpc_call,并将其保存在成员grpc_call *call_;中。只有当ext_ref为0时,才能删除此grpc_call指针。

当我与ClientReader同步使用grpc时:

  • 在其实现中,它使用CreateCall()和PerformOps()添加到ext_ref(ext_ref == 2)
  • 然后我使用Pluck(),它从ext_ref中减去,使得(ext_ref == 1)
  • 最后一次使用~ClientContext()从ext_ref中减去,以便ext_ref == 0并删除调用

但是当我与ClientAsyncReaderWriter异步使用grpc时:

  • 首先使用asyncXXX(),这个API使用CreateCall()和register Write()(ext_ref == 2)
  • 然后它使用AsyncNext()来获取标记。。。其必须使用写入或读取运算符
  • 所以ext_ref > 1永远存在,除非发生你无法处理的事件

我这样称呼它:

struct Notice
{
std::unique_ptr<
grpc::ClientAsyncReaderWriter<ObserveNoticRequest, EventNotice>
>                          _rw;
ClientContext              _context;
EventNotice                _rsp;
}

注册线程

CompletionQueue *cq = new CompletionQueue;
Notice *notice = new Notice;
notice->rw = stub->AsyncobserverNotice(&context, cq, notice); 
// here context.call_.ext_ref is 2

获取CompletionQueue事件线程

void *tag = NULL;
bool ok = false;
CompletionQueue::NextStatus got = CompletionQueue::NextStatus::TIMEOUT;
gpr_timespec deadline;
deadline.clock_type = GPR_TIMESPAN;
deadline.tv_sec = 0;
deadline.tv_nsec = 10000000;
got = cq->AsyncNext<gpr_timespec>(&tag, &ok, deadline);
if (GOT_EVENT == got) {
if (tag != NULL) {
Notice *notice = (Notice *)tag;
notice->_rw->Read(&_rsp, notice);
// here context.call_.ext_ref is 2.
// now I want to stop this CompletionQueue. 
delete notice;
// use ~ClientContext(), ext_ref change to 1
// but only ext_ref == 0, call_ be deleted
}
}

查看此文件client_async.cc,以了解ClientAsyncReaderWriter的良好使用情况。如果您仍有困惑,请创建一个非常干净的问题复制品,我们将对此进行进一步调查。

相关文章:
  • 没有找到相关文章