From bffc5701e6cd45ad24e358fc58602d344c756714 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Mon, 16 Dec 2019 13:39:21 -0800 Subject: [PATCH] Fix cancellation --- .../grpcpp/impl/codegen/server_callback_impl.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/include/grpcpp/impl/codegen/server_callback_impl.h b/include/grpcpp/impl/codegen/server_callback_impl.h index 8cbb8d6dafb..8ea902153e1 100644 --- a/include/grpcpp/impl/codegen/server_callback_impl.h +++ b/include/grpcpp/impl/codegen/server_callback_impl.h @@ -82,8 +82,7 @@ class ServerCallbackCall { // Fast version called with known reactor passed in, used from derived // classes, typically in non-cancel case void MaybeCallOnCancel(ServerReactor* reactor) { - if (GPR_UNLIKELY(on_cancel_conditions_remaining_.fetch_sub( - 1, std::memory_order_acq_rel) == 1)) { + if (GPR_UNLIKELY(UnblockCancellation())) { CallOnCancel(reactor); } } @@ -92,7 +91,11 @@ class ServerCallbackCall { // (such as the ServerContext CompletionOp which is formed before the // reactor). This is used in cancel cases only, so it's ok to be slower and // invoke a virtual function. - void MaybeCallOnCancel() { MaybeCallOnCancel(reactor()); } + void MaybeCallOnCancel() { + if (GPR_UNLIKELY(UnblockCancellation())) { + CallOnCancel(reactor()); + } + } protected: /// Increases the reference count @@ -111,6 +114,12 @@ class ServerCallbackCall { // it to an executor. void CallOnCancel(ServerReactor* reactor); + // Implement the cancellation constraint counter. Return true if OnCancel + // should be called, false otherwise. + bool UnblockCancellation() { + return on_cancel_conditions_remaining_.fetch_sub( + 1, std::memory_order_acq_rel) == 1; } + std::atomic_int on_cancel_conditions_remaining_{2}; std::atomic_int callbacks_outstanding_{ 3}; // reserve for start, Finish, and CompletionOp