Index: base/message_loop.cc |
=================================================================== |
--- base/message_loop.cc (revision 1892) |
+++ base/message_loop.cc (working copy) |
@@ -100,26 +100,28 @@ |
FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_, |
WillDestroyCurrentMessageLoop()); |
- // OK, now make it so that no one can find us. |
- tls_index_.Set(NULL); |
- |
DCHECK(!state_); |
- // Most tasks that have not been Run() are deleted in the |timer_manager_| |
- // destructor after we remove our tls index. We delete the tasks in our |
- // queues here so their destuction is similar to the tasks in the |
- // |timer_manager_|. |
- DeletePendingTasks(); |
- ReloadWorkQueue(); |
- DeletePendingTasks(); |
- |
- // Delete tasks in the delayed work queue. |
- while (!delayed_work_queue_.empty()) { |
- Task* task = delayed_work_queue_.top().task; |
- delayed_work_queue_.pop(); |
- delete task; |
+ // Clean up any unprocessed tasks, but take care: deleting a task could |
+ // result in the addition of more tasks (e.g., via DeleteSoon). We set a |
+ // limit on the number of times we will allow a deleted task to generate more |
+ // tasks. Normally, we should only pass through this loop once or twice. If |
+ // we end up hitting the loop limit, then it is probably due to one task that |
+ // is being stubborn. Inspect the queues to see who is left. |
+ bool did_work; |
+ for (int i = 0; i < 100; ++i) { |
+ DeletePendingTasks(); |
+ ReloadWorkQueue(); |
+ // If we end up with empty queues, then break out of the loop. |
+ did_work = DeletePendingTasks(); |
+ if (!did_work) |
+ break; |
} |
+ DCHECK(!did_work); |
+ // OK, now make it so that no one can find us. |
+ tls_index_.Set(NULL); |
+ |
#if defined(OS_WIN) |
// Match timeBeginPeriod() from construction. |
timeEndPeriod(1); |
@@ -312,6 +314,16 @@ |
return false; |
} |
+void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) { |
+ // Move to the delayed work queue. Initialize the sequence number |
+ // before inserting into the delayed_work_queue_. The sequence number |
+ // is used to faciliate FIFO sorting when two tasks have the same |
+ // delayed_run_time value. |
+ PendingTask new_pending_task(pending_task); |
+ new_pending_task.sequence_num = next_sequence_num_++; |
+ delayed_work_queue_.push(new_pending_task); |
+} |
+ |
void MessageLoop::ReloadWorkQueue() { |
// We can improve performance of our loading tasks from incoming_queue_ to |
// work_queue_ by waiting until the last minute (work_queue_ is empty) to |
@@ -330,20 +342,35 @@ |
} |
} |
-void MessageLoop::DeletePendingTasks() { |
- /* Comment this out as it's causing crashes. |
- while (!work_queue_.Empty()) { |
- Task* task = work_queue_.Pop(); |
- if (task->is_owned_by_message_loop()) |
- delete task; |
+bool MessageLoop::DeletePendingTasks() { |
+ bool did_work = !work_queue_.empty(); |
+ while (!work_queue_.empty()) { |
+ PendingTask pending_task = work_queue_.front(); |
+ work_queue_.pop(); |
+ if (!pending_task.delayed_run_time.is_null()) { |
+ // We want to delete delayed tasks in the same order in which they would |
+ // normally be deleted in case of any funny dependencies between delayed |
+ // tasks. |
+ AddToDelayedWorkQueue(pending_task); |
+ } else { |
+ // TODO(darin): Delete all tasks once it is safe to do so. |
+ //delete task; |
+ } |
} |
- |
- while (!delayed_non_nestable_queue_.Empty()) { |
- Task* task = delayed_non_nestable_queue_.Pop(); |
- if (task->is_owned_by_message_loop()) |
- delete task; |
+ did_work |= !deferred_non_nestable_work_queue_.empty(); |
+ while (!deferred_non_nestable_work_queue_.empty()) { |
+ Task* task = deferred_non_nestable_work_queue_.front().task; |
+ deferred_non_nestable_work_queue_.pop(); |
+ // TODO(darin): Delete all tasks once it is safe to do so. |
+ //delete task; |
} |
- */ |
+ did_work |= !delayed_work_queue_.empty(); |
+ while (!delayed_work_queue_.empty()) { |
+ Task* task = delayed_work_queue_.top().task; |
+ delayed_work_queue_.pop(); |
+ delete task; |
+ } |
+ return did_work; |
} |
bool MessageLoop::DoWork() { |
@@ -363,14 +390,7 @@ |
work_queue_.pop(); |
if (!pending_task.delayed_run_time.is_null()) { |
bool was_empty = delayed_work_queue_.empty(); |
- |
- // Move to the delayed work queue. Initialize the sequence number |
- // before inserting into the delayed_work_queue_. The sequence number |
- // is used to faciliate FIFO sorting when two tasks have the same |
- // delayed_run_time value. |
- pending_task.sequence_num = next_sequence_num_++; |
- delayed_work_queue_.push(pending_task); |
- |
+ AddToDelayedWorkQueue(pending_task); |
if (was_empty) // We only schedule the next delayed work item. |
pump_->ScheduleDelayedWork(pending_task.delayed_run_time); |
} else { |