|
|
|
@ -40,7 +40,9 @@ void LogicalThreadImpl::Run(std::function<void()> callback, |
|
|
|
|
this, location.file(), location.line()); |
|
|
|
|
} |
|
|
|
|
const size_t prev_size = size_.FetchAdd(1); |
|
|
|
|
if (prev_size == 0) { |
|
|
|
|
// The logical thread should not have been orphaned.
|
|
|
|
|
GPR_DEBUG_ASSERT(prev_size > 0); |
|
|
|
|
if (prev_size == 1) { |
|
|
|
|
// There is no other closure executing right now on this logical thread.
|
|
|
|
|
// Execute this closure immediately.
|
|
|
|
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_logical_thread_trace)) { |
|
|
|
@ -49,11 +51,6 @@ void LogicalThreadImpl::Run(std::function<void()> callback, |
|
|
|
|
callback(); |
|
|
|
|
// Loan this thread to the logical thread and drain the queue.
|
|
|
|
|
DrainQueue(); |
|
|
|
|
// It is possible that while draining the queue, one of the callbacks ended
|
|
|
|
|
// up orphaning the logical thread. In that case, delete the object.
|
|
|
|
|
if (orphaned_.Load(MemoryOrder::ACQUIRE)) { |
|
|
|
|
delete this; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
CallbackWrapper* cb_wrapper = |
|
|
|
|
new CallbackWrapper(std::move(callback), location); |
|
|
|
@ -67,10 +64,15 @@ void LogicalThreadImpl::Run(std::function<void()> callback, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void LogicalThreadImpl::Orphan() { |
|
|
|
|
if (size_.Load(MemoryOrder::ACQUIRE) == 0) { |
|
|
|
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_logical_thread_trace)) { |
|
|
|
|
gpr_log(GPR_INFO, "LogicalThread::Orphan() %p", this); |
|
|
|
|
} |
|
|
|
|
size_t prev_size = size_.FetchSub(1); |
|
|
|
|
if (prev_size == 0) { |
|
|
|
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_logical_thread_trace)) { |
|
|
|
|
gpr_log(GPR_INFO, " Destroying"); |
|
|
|
|
} |
|
|
|
|
delete this; |
|
|
|
|
} else { |
|
|
|
|
orphaned_.Store(true, MemoryOrder::RELEASE); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -85,11 +87,20 @@ void LogicalThreadImpl::DrainQueue() { |
|
|
|
|
} |
|
|
|
|
size_t prev_size = size_.FetchSub(1); |
|
|
|
|
GPR_DEBUG_ASSERT(prev_size >= 1); |
|
|
|
|
// It is possible that while draining the queue, one of the callbacks ended
|
|
|
|
|
// up orphaning the logical thread. In that case, delete the object.
|
|
|
|
|
if (prev_size == 1) { |
|
|
|
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_logical_thread_trace)) { |
|
|
|
|
gpr_log(GPR_INFO, " Queue Drained. Destroying"); |
|
|
|
|
} |
|
|
|
|
delete this; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (prev_size == 2) { |
|
|
|
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_logical_thread_trace)) { |
|
|
|
|
gpr_log(GPR_INFO, " Queue Drained"); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// There is atleast one callback on the queue. Pop the callback from the
|
|
|
|
|
// queue and execute it.
|
|
|
|
|