int IncomingTaskQueue::ReloadWorkQueue(TaskQueue* work_queue) {
// Make sure no tasks are lost.
DCHECK(work_queue->empty());
// Acquire all we can from the inter-thread queue with one lock acquisition.
AutoLock lock(incoming_queue_lock_);
if (incoming_queue_.empty()) {
// If the loop attempts to reload but there are no tasks in the incoming
// queue, that means it will go to sleep waiting for more work. If the
// incoming queue becomes nonempty we need to schedule it again.
message_loop_scheduled_ = false;
} else {
incoming_queue_.Swap(work_queue);
}
// Reset the count of high resolution tasks since our queue is now empty.
int high_res_tasks = high_res_task_count_;
high_res_task_count_ = 0;
return high_res_tasks;
}
void MessageLoop::ReloadWorkQueue() {
// We can improve performance of our loading tasks from the incoming queue to
// |*work_queue| by waiting until the last minute (|*work_queue| is empty) to
// load. That reduces the number of locks-per-task significantly when our
// queues get large.
if (work_queue_.empty()) {
incoming_task_queue_->ReloadWorkQueue(&work_queue_);
}
}
bool MessageLoop::DoWork() {
if (!nestable_tasks_allowed_) {
// Task can't be executed right now.
return false;
}
for (;;) {
ReloadWorkQueue();
if (work_queue_.empty())
break;
// Execute oldest task.
do {
PendingTask pending_task = work_queue_.front();
work_queue_.pop();
if (!pending_task.delayed_run_time.is_null()) {
AddToDelayedWorkQueue(pending_task);
// If we changed the topmost task, then it is time to reschedule.
if (delayed_work_queue_.top().task.Equals(pending_task.task))
pump_->ScheduleDelayedWork(pending_task.delayed_run_time);
} else {
if (DeferOrRunPendingTask(pending_task))
return true;
}
} while (!work_queue_.empty());
}
// Nothing happened.
return false;
}