aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/grpcpp/impl/codegen/callback_common.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/grpcpp/impl/codegen/callback_common.h')
-rw-r--r--include/grpcpp/impl/codegen/callback_common.h39
1 files changed, 27 insertions, 12 deletions
diff --git a/include/grpcpp/impl/codegen/callback_common.h b/include/grpcpp/impl/codegen/callback_common.h
index ca2f867d04..29deef658f 100644
--- a/include/grpcpp/impl/codegen/callback_common.h
+++ b/include/grpcpp/impl/codegen/callback_common.h
@@ -32,16 +32,16 @@ namespace grpc {
namespace internal {
/// An exception-safe way of invoking a user-specified callback function
-template <class Func, class Arg>
-void CatchingCallback(Func&& func, Arg&& arg) {
+template <class Func, class... Args>
+void CatchingCallback(Func&& func, Args&&... args) {
#if GRPC_ALLOW_EXCEPTIONS
try {
- func(arg);
+ func(std::forward<Args>(args)...);
} catch (...) {
// nothing to return or change here, just don't crash the library
}
#else // GRPC_ALLOW_EXCEPTIONS
- func(arg);
+ func(std::forward<Args>(args)...);
#endif // GRPC_ALLOW_EXCEPTIONS
}
@@ -94,14 +94,18 @@ class CallbackWithStatusTag
void Run(bool ok) {
void* ignored = ops_;
- GPR_CODEGEN_ASSERT(ops_->FinalizeResult(&ignored, &ok));
+ if (!ops_->FinalizeResult(&ignored, &ok)) {
+ // The tag was swallowed
+ return;
+ }
GPR_CODEGEN_ASSERT(ignored == ops_);
// Last use of func_ or status_, so ok to move them out
- CatchingCallback(std::move(func_), std::move(status_));
-
+ auto func = std::move(func_);
+ auto status = std::move(status_);
func_ = nullptr; // reset to clear this out for sure
status_ = Status(); // reset to clear this out for sure
+ CatchingCallback(std::move(func), std::move(status));
g_core_codegen_interface->grpc_call_unref(call_);
}
};
@@ -121,6 +125,8 @@ class CallbackWithSuccessTag
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { assert(0); }
+ CallbackWithSuccessTag() : call_(nullptr), ops_(nullptr) {}
+
CallbackWithSuccessTag(grpc_call* call, std::function<void(bool)> f,
CompletionQueueTag* ops)
: call_(call), func_(std::move(f)), ops_(ops) {
@@ -135,6 +141,9 @@ class CallbackWithSuccessTag
// that are detected before the operations are internally processed.
void force_run(bool ok) { Run(ok); }
+ /// check if this tag has ever been set
+ operator bool() const { return call_ != nullptr; }
+
private:
grpc_call* call_;
std::function<void(bool)> func_;
@@ -147,13 +156,19 @@ class CallbackWithSuccessTag
void Run(bool ok) {
void* ignored = ops_;
bool new_ok = ok;
- GPR_CODEGEN_ASSERT(ops_->FinalizeResult(&ignored, &new_ok));
+ // Allow a "false" return value from FinalizeResult to silence the
+ // callback, just as it silences a CQ tag in the async cases
+ bool do_callback = ops_->FinalizeResult(&ignored, &new_ok);
GPR_CODEGEN_ASSERT(ignored == ops_);
- // Last use of func_, so ok to move it out for rvalue call above
- CatchingCallback(std::move(func_), ok);
-
- func_ = nullptr; // reset to clear this out for sure
+ if (do_callback) {
+ // Last use of func_, so ok to move it out for rvalue call above
+ auto func = std::move(func_);
+ func_ = nullptr; // reset to clear this out for sure
+ CatchingCallback(std::move(func), ok);
+ } else {
+ func_ = nullptr; // reset to clear this out for sure
+ }
g_core_codegen_interface->grpc_call_unref(call_);
}
};