What is the mechanism of Completion Queue?

5,442 views
Skip to first unread message

hard...@gmail.com

unread,
Nov 4, 2015, 10:18:33 PM11/4/15
to grpc.io
Is there anyone familiar with CompleteQueue could tell me how the mechanism is? The only piece of codes I can found is 

  void HandleRpcs() {
   
// Spawn a new CallData instance to serve new clients.
   
new CallData(&service_, cq_.get());
   
void* tag;  // uniquely identifies a request.
   
bool ok;
   
while (true) {
     
// 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.
      cq_
->Next(&tag, &ok);
      GPR_ASSERT
(ok);
     
static_cast<CallData*>(tag)->Proceed();
   
}
 
}


I really would like to know how I could response to different kinds of request? And will the loop keep iterating over the CompleteQueue again and again?

robbins...@gmail.com

unread,
Dec 16, 2015, 1:01:12 PM12/16/15
to grpc.io
Hi all,

I'd like to understand this as well. There seems to be no place where the server determines what method to "spawn". In this specific example there is only one method that can be called but what if I have SayHello() and lets say -- sayGoodbye()? 

Any pointers much appreciated, thanks

/DF

Yang Gao

unread,
Dec 16, 2015, 1:12:37 PM12/16/15
to robbins...@gmail.com, grpc.io
In CallData constructor we call RequestSayHello with the cq and the this pointer of the CallData as the tag. This means we are asking for grpc server to give back a new SayHello rpc call on cq, and when the call comes, that tag will be returned. That is the reason why we can cast the tag we get back from the cq to a CallData. If you have another method, you need to explicitly call RequestSayGoodbye and give it a unique tag. When you get back the tag from the completion queue, you know you have a SayGoodbye call.

We will add a non-trivial async example soon.

--
You received this message because you are subscribed to the Google Groups "grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email to grpc-io+unsubscribe@googlegroups.com.
To post to this group, send email to grp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/grpc-io/d8490d01-8a6d-4ad8-b27c-9170363298cc%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

robbinson defau

unread,
Dec 16, 2015, 1:35:42 PM12/16/15
to Yang Gao, grpc.io
Yang, 

Thanks for the reply. I (think) I understand the casting and tagging part, however, what I fail to understand is how do you know that you need to call the RequestSayHello constructor and not the RequestSayGoodbye one.

In HandleRpcs(), new CallData(&service_, cq_.get()  It then calls Proceed() and somehow it already knows the RequestSayHello() method should be processed.  Or as per the example:

if (status_ == CREATE) {  service_->RequestSayHello(&ctx_, &request_, &responder_, cq_, cq_, this); } 

How would I add code here that does service_->RequestSayGoodbye is what I'm after. 

Thanks, and looking forward to some non-trivial examples!

/DF

To unsubscribe from this group and stop receiving emails from it, send an email to grpc-io+u...@googlegroups.com.

To post to this group, send email to grp...@googlegroups.com.

Caleb Epstein

unread,
Dec 16, 2015, 5:01:17 PM12/16/15
to grpc.io, ya...@google.com

On Wednesday, December 16, 2015 at 1:35:42 PM UTC-5, robbinson defau wrote:

How would I add code here that does service_->RequestSayGoodbye is what I'm after. 

You'd need to change the CallStatus enum and the state machine that processes it (Proceed function).  If you say hello, then say goodbye, just add another state called, perhaps, GOODBYE.  When PROCESS is finished, transition to GOODBYE state instead of FINISH.  When the status is GOODBYE, call the new function and then transition to the FINISH state.

Yang Gao

unread,
Dec 16, 2015, 5:35:22 PM12/16/15
to robbinson defau, grpc.io
A simple example can be found at https://github.com/grpc/grpc/commit/7cd14c2b72c3acf8898164784999a9b96c7804ca

You need to call RequestX for each method you want to handle and pass unique tags to them. Then according to the tag you get back from cq, handle them for each method. 

To unsubscribe from this group and stop receiving emails from it, send an email to grpc-io+unsubscribe@googlegroups.com.

To post to this group, send email to grp...@googlegroups.com.

robbinson defau

unread,
Dec 17, 2015, 4:01:42 AM12/17/15
to Yang Gao, grpc.io
Thanks for the prompt replies and toy example, most helpful!

/DF

To unsubscribe from this group and stop receiving emails from it, send an email to grpc-io+u...@googlegroups.com.

To post to this group, send email to grp...@googlegroups.com.

zog Lee

unread,
Jan 24, 2016, 9:51:50 PM1/24/16
to grpc.io, robbins...@gmail.com
在 2015年12月17日星期四 UTC+8上午2:12:37,Yang Gao写道:
In CallData constructor we call RequestSayHello with the cq and the this pointer of the CallData as the tag. This means we are asking for grpc server to give back a new SayHello rpc call on cq, and when the call comes, that tag will be returned. That is the reason why we can cast the tag we get back from the cq to a CallData. If you have another method, you need to explicitly call RequestSayGoodbye and give it a unique tag. When you get back the tag from the completion queue, you know you have a SayGoodbye call.

 so, here is my understanding:
 RequestX likes doing "I want to listen on X request", so when cq_->Next() recv the tag binding to X request, that means one X request had recved by the grpc runtime, and now the logic code should do something, and call Xresponder->Finish(reply, status, tag); to tell grpc runtime to send status and reply to peer.

And here is my questions:
Q1: If we call RequestX multiple times before the cq_Next(), what that means for  and what will happen when we do cq_->Next() ?
Q2: If we just have one cq and multiple RequestX at the same time(just like the greet_async_server.cc does), how many OS threads are used to execute those "CallData" ?
Q3: If we create multiple cq, how many OS threads are used to execute those "CallData" ?

Yang Gao

unread,
Jan 26, 2016, 7:53:38 PM1/26/16
to grpc.io, robbins...@gmail.com
You can have many pending RequestX calls as long as they have unique tags. When you call cq->Next(), you will get the tags back.
Each cq->Next will block a thread. You can use one cq and call cq->Next in different threads.

dali...@gmail.com

unread,
Mar 16, 2019, 1:36:51 AM3/16/19
to grpc.io
In Proceed(), there are three states {CREATE, PROCESS, FINISH}. In the FINISH state, we free the memory of CallData.
However, HandleRpc() only call proceed() once,. It seems we always stay in the PROCESS state. Will it generate the memory leak?

Mohan Gyara

unread,
May 30, 2021, 3:44:25 PM5/30/21
to grpc.io
What does it mean to have cq->next(&tag, &ok) return the out param ok as false? 
I appreciate if someone answer this. 

Regards,
Mohan

yas...@google.com

unread,
Jun 16, 2021, 1:22:19 PM6/16/21
to grpc.io
> However, HandleRpc() only call proceed() once,. It seems we always stay in the PROCESS state. Will it generate the memory leak?

No, the same CallData object is used multiple times as a completion queue tag, allowing the state to progress.

> What does it mean to have cq->next(&tag, &ok) return the out param ok as false? 

A `false` value for `ok` signifies a failure to read a successful event, but the documentation already mentions that. Do you have a more specific question that you have in mind?
Reply all
Reply to author
Forward
0 new messages