2

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

struct grpc_call有一个gpr_refcount名为的类型的成员ext_ref。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() 并注册 Write() ( ext_ref == 2)。
  • 然后它使用 AsyncNext() 来获取标签...必须使用写入或读取运算符。
  • 所以ext_ref > 1永远,除非 got_event 你不处理。

我这样称呼它:

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
    }
}
4

1 回答 1

2

查看此文件client_async.cc,以充分利用 ClientAsyncReaderWriter。如果您仍然有困惑,请创建一个非常清晰的问题再现,我们将进一步调查。

于 2017-10-27T16:49:48.127 回答