Index: third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc |
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc |
index b534f5179759da5509ce80c1d50b6c27dd8e7759..1493997a88f4d3df7e54b516aa0d679bf447a000 100644 |
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc |
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc |
@@ -93,7 +93,7 @@ TaskQueueImpl::TaskQueueImpl( |
TaskQueueImpl::~TaskQueueImpl() { |
#if DCHECK_IS_ON() |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
// NOTE this check shouldn't fire because |TaskQueueManager::queues_| |
// contains a strong reference to this TaskQueueImpl and the TaskQueueManager |
// destructor calls UnregisterTaskQueue on all task queues. |
@@ -163,12 +163,13 @@ TaskQueueImpl::MainThreadOnly::MainThreadOnly( |
is_enabled_refcount(0), |
voter_refcount(0), |
blame_context(nullptr), |
- current_fence(0) {} |
+ current_fence(0), |
+ any_thread_lock_acquired_count(0) {} |
TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |
void TaskQueueImpl::UnregisterTaskQueue() { |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
if (main_thread_only().time_domain) |
main_thread_only().time_domain->UnregisterQueue(this); |
if (!any_thread().task_queue_manager) |
@@ -212,7 +213,7 @@ bool TaskQueueImpl::PostImmediateTaskImpl( |
const tracked_objects::Location& from_here, |
const base::Closure& task, |
TaskType task_type) { |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
if (!any_thread().task_queue_manager) |
return false; |
@@ -253,7 +254,7 @@ bool TaskQueueImpl::PostDelayedTaskImpl( |
// be common. This pathway is less optimal than perhaps it could be |
// because it causes two main thread tasks to be run. Should this |
// assumption prove to be false in future, we may need to revisit this. |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
if (!any_thread().task_queue_manager) |
return false; |
@@ -358,7 +359,7 @@ void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() { |
} |
WTF::Deque<TaskQueueImpl::Task> TaskQueueImpl::TakeImmediateIncomingQueue() { |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
WTF::Deque<TaskQueueImpl::Task> queue; |
queue.swap(any_thread().immediate_incoming_queue); |
return queue; |
@@ -371,7 +372,7 @@ bool TaskQueueImpl::IsEmpty() const { |
return false; |
} |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
return any_thread().immediate_incoming_queue.empty(); |
} |
@@ -381,7 +382,7 @@ size_t TaskQueueImpl::GetNumberOfPendingTasks() const { |
task_count += main_thread_only().delayed_incoming_queue.size(); |
task_count += main_thread_only().immediate_work_queue->Size(); |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
task_count += any_thread().immediate_incoming_queue.size(); |
return task_count; |
} |
@@ -402,7 +403,7 @@ bool TaskQueueImpl::HasPendingImmediateWork() const { |
} |
// Finally tasks on |immediate_incoming_queue| count as immediate work. |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
return !any_thread().immediate_incoming_queue.empty(); |
} |
@@ -490,7 +491,7 @@ TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { |
} |
void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
state->BeginDictionary(); |
state->SetString("name", GetName()); |
state->SetString( |
@@ -568,7 +569,7 @@ void TaskQueueImpl::NotifyDidProcessTask( |
void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) { |
{ |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
DCHECK(time_domain); |
// NOTE this is similar to checking |any_thread().task_queue_manager| but |
// the TaskQueueSelectorTests constructs TaskQueueImpl directly with a null |
@@ -601,7 +602,7 @@ TimeDomain* TaskQueueImpl::GetTimeDomain() const { |
if (base::PlatformThread::CurrentId() == thread_id_) |
return main_thread_only().time_domain; |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
return any_thread().time_domain; |
} |
@@ -629,7 +630,7 @@ void TaskQueueImpl::InsertFence(TaskQueue::InsertFencePosition position) { |
if (!task_unblocked && previous_fence && |
previous_fence < main_thread_only().current_fence) { |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
if (!any_thread().immediate_incoming_queue.empty() && |
any_thread().immediate_incoming_queue.front().enqueue_order() > |
previous_fence && |
@@ -656,7 +657,7 @@ void TaskQueueImpl::RemoveFence() { |
task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); |
if (!task_unblocked && previous_fence) { |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
if (!any_thread().immediate_incoming_queue.empty() && |
any_thread().immediate_incoming_queue.front().enqueue_order() > |
previous_fence) { |
@@ -679,7 +680,7 @@ bool TaskQueueImpl::BlockedByFence() const { |
return false; |
} |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
if (any_thread().immediate_incoming_queue.empty()) |
return true; |
@@ -812,7 +813,7 @@ void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) { |
bool immediate_queues_empty = |
main_thread_only().immediate_work_queue->Empty(); |
if (immediate_queues_empty) { |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
immediate_queues_empty = any_thread().immediate_incoming_queue.empty(); |
} |
// Avoid holding the lock while we fire the notification. |
@@ -879,10 +880,38 @@ void TaskQueueImpl::SweepCanceledDelayedTasks(base::TimeTicks now) { |
void TaskQueueImpl::PushImmediateIncomingTaskForTest( |
TaskQueueImpl::Task&& task) { |
- base::AutoLock lock(any_thread_lock_); |
+ AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
any_thread().immediate_incoming_queue.push_back(std::move(task)); |
} |
+TaskQueueImpl::AnyThreadAutoLock TaskQueueImpl::AcquireAnyThreadLock() const { |
+ size_t* any_thread_lock_acquired_from_main_thread_count = nullptr; |
+ if (thread_id_ == base::PlatformThread::CurrentId()) |
+ any_thread_lock_acquired_from_main_thread_count = |
+ &main_thread_only().any_thread_lock_acquired_count; |
+ return AnyThreadAutoLock(any_thread_lock_, |
+ any_thread_lock_acquired_from_main_thread_count); |
+} |
+ |
+TaskQueueImpl::AnyThreadAutoLock::AnyThreadAutoLock(base::Lock& lock, |
+ size_t* acquired_count) |
+ : lock_(lock), acquired_count_(acquired_count) { |
+ if (!acquired_count_ || *acquired_count_ == 0) { |
+ lock_.Acquire(); |
+ } |
+ if (acquired_count_) |
+ ++*acquired_count_; |
+ lock_.AssertAcquired(); |
+} |
+ |
+TaskQueueImpl::AnyThreadAutoLock::~AnyThreadAutoLock() { |
+ lock_.AssertAcquired(); |
+ if (acquired_count_) |
+ --*acquired_count_; |
+ if (!acquired_count_ || *acquired_count_ == 0) |
+ lock_.Release(); |
+} |
+ |
} // namespace internal |
} // namespace scheduler |
} // namespace blink |