Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Unified Diff: third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc

Issue 2653643002: Move has_incoming_immediate_work to the TaskQueueManager (Closed)
Patch Set: Add some tracing Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
index fdb9ec552dba08516b56fc49acbfba44accbe987..cb80df6bdc14444c0a19420030066840c47ccbd9 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
@@ -147,18 +147,33 @@ void TaskQueueManager::UnregisterTaskQueue(
queues_.erase(task_queue);
selector_.RemoveQueue(task_queue.get());
+
+ {
+ base::AutoLock lock(any_thread_lock_);
+ any_thread().has_incoming_immediate_work.erase(task_queue.get());
+ }
+}
+
+void TaskQueueManager::ReloadEmptyWorkQueues(
+ const std::set<internal::TaskQueueImpl*>& queues_to_reload) const {
+ // There are two cases where a queue needs reloading. First, it might be
+ // completely empty and we've just posted a task (this method handles that
+ // case). Secondly
Sami 2017/01/24 14:52:40 Secondly...? :)
alex clarke (OOO till 29th) 2017/01/24 15:28:14 Done.
+ for (internal::TaskQueueImpl* queue : queues_to_reload) {
+ queue->ReloadImmediateWorkQueueIfEmpty();
+ }
}
-void TaskQueueManager::UpdateWorkQueues(LazyNow* lazy_now) {
+void TaskQueueManager::WakeupReadyDelayedQueues(LazyNow* lazy_now) {
TRACE_EVENT0(disabled_by_default_tracing_category_,
- "TaskQueueManager::UpdateWorkQueues");
+ "TaskQueueManager::WakeupReadyDelayedQueues");
for (TimeDomain* time_domain : time_domains_) {
if (time_domain == real_time_domain_.get()) {
- time_domain->UpdateWorkQueues(lazy_now);
+ time_domain->WakeupReadyDelayedQueues(lazy_now);
} else {
LazyNow time_domain_lazy_now = time_domain->CreateLazyNow();
- time_domain->UpdateWorkQueues(&time_domain_lazy_now);
+ time_domain->WakeupReadyDelayedQueues(&time_domain_lazy_now);
}
}
}
@@ -169,6 +184,37 @@ void TaskQueueManager::OnBeginNestedMessageLoop() {
delegate_->PostTask(FROM_HERE, from_main_thread_immediate_do_work_closure_);
}
+void TaskQueueManager::OnQueueHasIncomingImmediateWork(
+ internal::TaskQueueImpl* queue,
+ bool ensure_do_work_posted) {
+ bool on_main_thread = delegate_->BelongsToCurrentThread();
+
+ {
+ base::AutoLock lock(any_thread_lock_);
+ any_thread().has_incoming_immediate_work.insert(queue);
+
+ if (!ensure_do_work_posted)
+ return;
+
+ // De-duplicate DoWork posts.
+ if (on_main_thread) {
+ if (!main_thread_pending_wakeups_.insert(base::TimeTicks()).second)
+ return;
+ } else {
+ if (any_thread().other_thread_pending_wakeup)
+ return;
+ any_thread().other_thread_pending_wakeup = true;
+ }
+ }
+
+ if (on_main_thread) {
+ delegate_->PostTask(FROM_HERE, from_main_thread_immediate_do_work_closure_);
+ } else {
+ delegate_->PostTask(FROM_HERE,
+ from_other_thread_immediate_do_work_closure_);
+ }
+}
+
void TaskQueueManager::MaybeScheduleImmediateWork(
const tracked_objects::Location& from_here) {
bool on_main_thread = delegate_->BelongsToCurrentThread();
@@ -237,9 +283,20 @@ void TaskQueueManager::DoWork(base::TimeTicks run_time, bool from_main_thread) {
queues_to_delete_.clear();
LazyNow lazy_now(real_time_domain()->CreateLazyNow());
- UpdateWorkQueues(&lazy_now);
+ WakeupReadyDelayedQueues(&lazy_now);
for (int i = 0; i < work_batch_size_; i++) {
+ std::set<internal::TaskQueueImpl*> queues_to_reload;
Sami 2017/01/24 14:52:40 Probably doesn't make a huge difference, but unord
alex clarke (OOO till 29th) 2017/01/24 15:28:14 I guess.
+
+ {
+ base::AutoLock lock(any_thread_lock_);
+ std::swap(queues_to_reload, any_thread().has_incoming_immediate_work);
+ }
+
+ // It's important we call ReloadEmptyWorkQueues out side of the lock to
+ // avoid a lock order inversion.
+ ReloadEmptyWorkQueues(queues_to_reload);
+
internal::WorkQueue* work_queue;
if (!SelectWorkQueueToService(&work_queue))
break;
@@ -260,7 +317,7 @@ void TaskQueueManager::DoWork(base::TimeTicks run_time, bool from_main_thread) {
lazy_now = time_after_task.is_null() ? real_time_domain()->CreateLazyNow()
: LazyNow(time_after_task);
- UpdateWorkQueues(&lazy_now);
+ WakeupReadyDelayedQueues(&lazy_now);
// Only run a single task per batch in nested run loops so that we can
// properly exit the nested loop when someone calls RunLoop::Quit().
@@ -289,11 +346,26 @@ void TaskQueueManager::DoWork(base::TimeTicks run_time, bool from_main_thread) {
base::Optional<base::TimeDelta> TaskQueueManager::ComputeDelayTillNextTask(
LazyNow* lazy_now) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+
// If the selector has non-empty queues we trivially know there is immediate
// work to be done.
if (!selector_.EnabledWorkQueuesEmpty())
return base::TimeDelta();
+ {
+ base::AutoLock lock(any_thread_lock_);
Sami 2017/01/24 14:52:40 Any lock inversion issues here? Basically I think
alex clarke (OOO till 29th) 2017/01/24 15:28:14 Yeah actually that could be one. Can probably get
alex clarke (OOO till 29th) 2017/01/24 15:29:11 Actually on second thoughts I think I'm trying to
+ // If we have incoming immediate work for any queue able to run, we know
+ // there is immediate work to be done.
+ for (internal::TaskQueueImpl* queue :
+ any_thread().has_incoming_immediate_work) {
+ // Note when posted ImmediateTaskCouldRun would have returned true but
+ // conditions may have changed since then.
+ if (queue->ImmediateTaskCouldRun())
+ return base::TimeDelta();
+ }
+ }
+
// Otherwise we need to find the shortest delay, if any.
base::Optional<base::TimeDelta> next_continuation;
for (TimeDomain* time_domain : time_domains_) {
@@ -505,6 +577,15 @@ TaskQueueManager::AsValueWithSelectorResult(
for (auto* time_domain : time_domains_)
time_domain->AsValueInto(state.get());
state->EndArray();
+ {
+ base::AutoLock lock(any_thread_lock_);
+ state->BeginArray("has_incoming_immediate_work");
+ for (internal::TaskQueueImpl* task_queue :
+ any_thread().has_incoming_immediate_work) {
+ state->AppendString(task_queue->GetName());
+ }
+ state->EndArray();
+ }
return std::move(state);
}

Powered by Google App Engine
This is Rietveld 408576698