Change behavior to properly account for possibility of NULL

tag. This can happen if the tag is actually an integer being
typecast to void*

To avoid breaking the API of existing Next calls, I've made
a new AsyncNext method with a tri-state return that indicates
whether there is a shutdown, an actual event, or a timeout.

Still needs proper testing for the AsyncNext method specifically.
pull/1023/head
Vijay Pai 10 years ago
parent ee705f6d66
commit 3e0a46a1c4
  1. 15
      include/grpc++/completion_queue.h
  2. 11
      src/cpp/common/completion_queue.cc

@ -76,10 +76,19 @@ class CompletionQueue {
explicit CompletionQueue(grpc_completion_queue *take); explicit CompletionQueue(grpc_completion_queue *take);
~CompletionQueue(); ~CompletionQueue();
// Tri-state return for Next: SHUTDOWN, GOT_EVENT, TIMEOUT
enum NextStatus {SHUTDOWN, GOT_EVENT, TIMEOUT};
// Blocking (until deadline) read from queue. // Blocking (until deadline) read from queue.
// Returns false if the queue is ready for destruction, true otherwise // Returns false if the queue is ready for destruction, true if event
// If the deadline passed, *tag will be null
bool Next(void **tag, bool *ok, gpr_timespec deadline=gpr_inf_future); bool Next(void **tag, bool *ok) {
return (AsyncNext(tag,ok,gpr_inf_future) != SHUTDOWN);
}
// Nonblocking (until deadline) read from queue.
// Cannot rely on result of tag or ok if return is TIMEOUT
NextStatus AsyncNext(void **tag, bool *ok, gpr_timespec deadline);
// Shutdown has to be called, and the CompletionQueue can only be // Shutdown has to be called, and the CompletionQueue can only be
// destructed when false is returned from Next(). // destructed when false is returned from Next().

@ -57,24 +57,23 @@ class EventDeleter {
} }
}; };
bool CompletionQueue::Next(void** tag, bool* ok, gpr_timespec deadline) { CompletionQueue::NextStatus CompletionQueue::AsyncNext(void** tag, bool* ok,
gpr_timespec deadline) {
std::unique_ptr<grpc_event, EventDeleter> ev; std::unique_ptr<grpc_event, EventDeleter> ev;
for (;;) { for (;;) {
ev.reset(grpc_completion_queue_next(cq_, deadline)); ev.reset(grpc_completion_queue_next(cq_, deadline));
if (!ev) { /* got a NULL back because deadline passed */ if (!ev) { /* got a NULL back because deadline passed */
*ok = true; return TIMEOUT;
*tag = nullptr;
return true;
} }
if (ev->type == GRPC_QUEUE_SHUTDOWN) { if (ev->type == GRPC_QUEUE_SHUTDOWN) {
return false; return SHUTDOWN;
} }
auto cq_tag = static_cast<CompletionQueueTag*>(ev->tag); auto cq_tag = static_cast<CompletionQueueTag*>(ev->tag);
*ok = ev->data.op_complete == GRPC_OP_OK; *ok = ev->data.op_complete == GRPC_OP_OK;
*tag = cq_tag; *tag = cq_tag;
if (cq_tag->FinalizeResult(tag, ok)) { if (cq_tag->FinalizeResult(tag, ok)) {
return true; return GOT_EVENT;
} }
} }
} }

Loading…
Cancel
Save