我找不到显示如何使用 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
}
}