|
|
|
@ -33,18 +33,27 @@ DebugOnlyTraceFlag grpc_call_combiner_trace(false, "call_combiner"); |
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
|
|
|
|
constexpr static intptr_t kErrorBit = |
|
|
|
|
#ifdef GRPC_ERROR_IS_ABSEIL_STATUS |
|
|
|
|
// absl::Status: 2nd bit from LSB can be used.
|
|
|
|
|
// (1st bit is reserved for absl::Status inline bit.)
|
|
|
|
|
2; |
|
|
|
|
#else |
|
|
|
|
// grpc_error LSB can be used
|
|
|
|
|
1; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
grpc_error_handle DecodeCancelStateError(gpr_atm cancel_state) { |
|
|
|
|
if (cancel_state & 1) { |
|
|
|
|
return reinterpret_cast<grpc_error_handle>(cancel_state & |
|
|
|
|
~static_cast<gpr_atm>(1)); |
|
|
|
|
if (cancel_state & kErrorBit) { |
|
|
|
|
#ifdef GRPC_ERROR_IS_ABSEIL_STATUS |
|
|
|
|
return internal::StatusGetFromPtr(cancel_state & ~kErrorBit); |
|
|
|
|
#else |
|
|
|
|
return reinterpret_cast<grpc_error_handle>(cancel_state & ~kErrorBit); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
return GRPC_ERROR_NONE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gpr_atm EncodeCancelStateError(grpc_error_handle error) { |
|
|
|
|
return static_cast<gpr_atm>(1) | reinterpret_cast<gpr_atm>(error); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
CallCombiner::CallCombiner() { |
|
|
|
@ -57,7 +66,14 @@ CallCombiner::CallCombiner() { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CallCombiner::~CallCombiner() { |
|
|
|
|
GRPC_ERROR_UNREF(DecodeCancelStateError(cancel_state_)); |
|
|
|
|
if (cancel_state_ & kErrorBit) { |
|
|
|
|
#ifdef GRPC_ERROR_IS_ABSEIL_STATUS |
|
|
|
|
internal::StatusFreePtr(cancel_state_ & ~kErrorBit); |
|
|
|
|
#else |
|
|
|
|
GRPC_ERROR_UNREF(reinterpret_cast<grpc_error_handle>( |
|
|
|
|
cancel_state_ & ~static_cast<gpr_atm>(kErrorBit))); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef GRPC_TSAN_ENABLED |
|
|
|
@ -235,15 +251,29 @@ void CallCombiner::SetNotifyOnCancel(grpc_closure* closure) { |
|
|
|
|
|
|
|
|
|
void CallCombiner::Cancel(grpc_error_handle error) { |
|
|
|
|
GRPC_STATS_INC_CALL_COMBINER_CANCELLED(); |
|
|
|
|
#ifdef GRPC_ERROR_IS_ABSEIL_STATUS |
|
|
|
|
intptr_t status_ptr = internal::StatusAllocPtr(error); |
|
|
|
|
if ((status_ptr & kErrorBit) > 0) { |
|
|
|
|
// absl::Status shouldn't have kErrorBit, could be a code bug.
|
|
|
|
|
gpr_log(GPR_ERROR, "CallCombiner::Cancel got an error which has kErrorBit"); |
|
|
|
|
abort(); |
|
|
|
|
} |
|
|
|
|
gpr_atm new_state = kErrorBit | status_ptr; |
|
|
|
|
#else |
|
|
|
|
gpr_atm new_state = kErrorBit | reinterpret_cast<gpr_atm>(error); |
|
|
|
|
#endif |
|
|
|
|
while (true) { |
|
|
|
|
gpr_atm original_state = gpr_atm_acq_load(&cancel_state_); |
|
|
|
|
grpc_error_handle original_error = DecodeCancelStateError(original_state); |
|
|
|
|
if (original_error != GRPC_ERROR_NONE) { |
|
|
|
|
#ifdef GRPC_ERROR_IS_ABSEIL_STATUS |
|
|
|
|
internal::StatusFreePtr(status_ptr); |
|
|
|
|
#else |
|
|
|
|
GRPC_ERROR_UNREF(error); |
|
|
|
|
#endif |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if (gpr_atm_full_cas(&cancel_state_, original_state, |
|
|
|
|
EncodeCancelStateError(error))) { |
|
|
|
|
if (gpr_atm_full_cas(&cancel_state_, original_state, new_state)) { |
|
|
|
|
if (original_state != 0) { |
|
|
|
|
grpc_closure* notify_on_cancel = |
|
|
|
|
reinterpret_cast<grpc_closure*>(original_state); |
|
|
|
|