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

Unified Diff: base/message_loop/incoming_task_queue.cc

Issue 1991623002: Avoid holding |incoming_queue_lock_| while waking up the message loop. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@base-rw-lock
Patch Set: Rebase Created 4 years, 7 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
« no previous file with comments | « base/message_loop/incoming_task_queue.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/message_loop/incoming_task_queue.cc
diff --git a/base/message_loop/incoming_task_queue.cc b/base/message_loop/incoming_task_queue.cc
index 470e44b244b2d700c23bf26afd13c95f2133cbb5..8298c281de21b6398b6879549540a94bb11086cf 100644
--- a/base/message_loop/incoming_task_queue.cc
+++ b/base/message_loop/incoming_task_queue.cc
@@ -68,8 +68,7 @@ bool IncomingTaskQueue::AddToIncomingQueue(
<< " seconds from here: " << from_here.ToString();
PendingTask pending_task(
- from_here, task, CalculateDelayedRuntime(delay), nestable);
- AutoLock locked(incoming_queue_lock_);
+ from_here, task, CalculateDelayedRuntime(delay), nestable);
#if defined(OS_WIN)
// We consider the task needs a high resolution timer if the delay is
// more than 0 and less than 32ms. This caps the relative error to
@@ -77,7 +76,6 @@ bool IncomingTaskQueue::AddToIncomingQueue(
// resolution on Windows is between 10 and 15ms.
if (delay > TimeDelta() &&
delay.InMilliseconds() < (2 * Time::kMinLowResolutionThresholdMs)) {
- ++high_res_task_count_;
pending_task.is_high_res = true;
}
#endif
@@ -115,17 +113,25 @@ int IncomingTaskQueue::ReloadWorkQueue(TaskQueue* work_queue) {
}
void IncomingTaskQueue::WillDestroyCurrentMessageLoop() {
- AutoLock lock(incoming_queue_lock_);
+ base::subtle::AutoWriteLock lock(message_loop_lock_);
message_loop_ = NULL;
}
void IncomingTaskQueue::StartScheduling() {
- AutoLock lock(incoming_queue_lock_);
- DCHECK(!is_ready_for_scheduling_);
- DCHECK(!message_loop_scheduled_);
- is_ready_for_scheduling_ = true;
- if (!incoming_queue_.empty())
- ScheduleWork();
+ bool schedule_work;
+ {
+ AutoLock lock(incoming_queue_lock_);
+ DCHECK(!is_ready_for_scheduling_);
+ DCHECK(!message_loop_scheduled_);
+ is_ready_for_scheduling_ = true;
+ schedule_work = !incoming_queue_.empty();
+ }
+ if (schedule_work) {
+ DCHECK(message_loop_);
+ // Don't need to lock |message_loop_lock_| here because this function is
+ // called by MessageLoop on its thread.
+ message_loop_->ScheduleWork();
+ }
}
IncomingTaskQueue::~IncomingTaskQueue() {
@@ -138,44 +144,55 @@ bool IncomingTaskQueue::PostPendingTask(PendingTask* pending_task) {
// directly, as it could starve handling of foreign threads. Put every task
// into this queue.
- // This should only be called while the lock is taken.
- incoming_queue_lock_.AssertAcquired();
+ // Ensures |message_loop_| isn't destroyed while running.
+ base::subtle::AutoReadLock hold_message_loop(message_loop_lock_);
if (!message_loop_) {
pending_task->task.Reset();
return false;
}
- // Initialize the sequence number. The sequence number is used for delayed
- // tasks (to facilitate FIFO sorting when two tasks have the same
- // delayed_run_time value) and for identifying the task in about:tracing.
- pending_task->sequence_num = next_sequence_num_++;
-
- message_loop_->task_annotator()->DidQueueTask("MessageLoop::PostTask",
- *pending_task);
+ bool schedule_work = false;
+ {
+ AutoLock hold(incoming_queue_lock_);
- bool was_empty = incoming_queue_.empty();
- incoming_queue_.push(*pending_task);
- pending_task->task.Reset();
+#if defined(OS_WIN)
+ if (pending_task->is_high_res)
+ ++high_res_task_count_;
+#endif
- if (is_ready_for_scheduling_ &&
- (always_schedule_work_ || (!message_loop_scheduled_ && was_empty))) {
- ScheduleWork();
+ // Initialize the sequence number. The sequence number is used for delayed
+ // tasks (to facilitate FIFO sorting when two tasks have the same
+ // delayed_run_time value) and for identifying the task in about:tracing.
+ pending_task->sequence_num = next_sequence_num_++;
+
+ message_loop_->task_annotator()->DidQueueTask("MessageLoop::PostTask",
+ *pending_task);
+
+ bool was_empty = incoming_queue_.empty();
+ incoming_queue_.push(std::move(*pending_task));
+
+ if (is_ready_for_scheduling_ &&
+ (always_schedule_work_ || (!message_loop_scheduled_ && was_empty))) {
+ schedule_work = true;
+ // After we've scheduled the message loop, we do not need to do so again
+ // until we know it has processed all of the work in our queue and is
+ // waiting for more work again. The message loop will always attempt to
+ // reload from the incoming queue before waiting again so we clear this
+ // flag in ReloadWorkQueue().
+ message_loop_scheduled_ = true;
+ }
}
- return true;
-}
+ // Wake up the message loop and schedule work. This is done outside
+ // |incoming_queue_lock_| because signaling the message loop may cause this
+ // thread to be switched. If |incoming_queue_lock_| is held, any other thread
+ // that wants to post a task will be blocked until this thread switches back
+ // in and releases |incoming_queue_lock_|.
+ if (schedule_work)
+ message_loop_->ScheduleWork();
-void IncomingTaskQueue::ScheduleWork() {
- DCHECK(is_ready_for_scheduling_);
- // Wake up the message loop.
- message_loop_->ScheduleWork();
- // After we've scheduled the message loop, we do not need to do so again
- // until we know it has processed all of the work in our queue and is
- // waiting for more work again. The message loop will always attempt to
- // reload from the incoming queue before waiting again so we clear this flag
- // in ReloadWorkQueue().
- message_loop_scheduled_ = true;
+ return true;
}
} // namespace internal
« no previous file with comments | « base/message_loop/incoming_task_queue.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698