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

Side by Side Diff: base/message_loop.cc

Issue 1664: Put back r1891 with some task deletion disabled to maintain backwards compat... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 3 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/message_loop.h ('k') | base/message_loop_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/message_loop.h" 5 #include "base/message_loop.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #if defined(OS_WIN) 9 #if defined(OS_WIN)
10 #include <mmsystem.h> 10 #include <mmsystem.h>
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 #endif 93 #endif
94 } 94 }
95 95
96 MessageLoop::~MessageLoop() { 96 MessageLoop::~MessageLoop() {
97 DCHECK(this == current()); 97 DCHECK(this == current());
98 98
99 // Let interested parties have one last shot at accessing this. 99 // Let interested parties have one last shot at accessing this.
100 FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_, 100 FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_,
101 WillDestroyCurrentMessageLoop()); 101 WillDestroyCurrentMessageLoop());
102 102
103 DCHECK(!state_);
104
105 // Clean up any unprocessed tasks, but take care: deleting a task could
106 // result in the addition of more tasks (e.g., via DeleteSoon). We set a
107 // limit on the number of times we will allow a deleted task to generate more
108 // tasks. Normally, we should only pass through this loop once or twice. If
109 // we end up hitting the loop limit, then it is probably due to one task that
110 // is being stubborn. Inspect the queues to see who is left.
111 bool did_work;
112 for (int i = 0; i < 100; ++i) {
113 DeletePendingTasks();
114 ReloadWorkQueue();
115 // If we end up with empty queues, then break out of the loop.
116 did_work = DeletePendingTasks();
117 if (!did_work)
118 break;
119 }
120 DCHECK(!did_work);
121
103 // OK, now make it so that no one can find us. 122 // OK, now make it so that no one can find us.
104 tls_index_.Set(NULL); 123 tls_index_.Set(NULL);
105 124
106 DCHECK(!state_);
107
108 // Most tasks that have not been Run() are deleted in the |timer_manager_|
109 // destructor after we remove our tls index. We delete the tasks in our
110 // queues here so their destuction is similar to the tasks in the
111 // |timer_manager_|.
112 DeletePendingTasks();
113 ReloadWorkQueue();
114 DeletePendingTasks();
115
116 // Delete tasks in the delayed work queue.
117 while (!delayed_work_queue_.empty()) {
118 Task* task = delayed_work_queue_.top().task;
119 delayed_work_queue_.pop();
120 delete task;
121 }
122
123 #if defined(OS_WIN) 125 #if defined(OS_WIN)
124 // Match timeBeginPeriod() from construction. 126 // Match timeBeginPeriod() from construction.
125 timeEndPeriod(1); 127 timeEndPeriod(1);
126 #endif 128 #endif
127 } 129 }
128 130
129 void MessageLoop::AddDestructionObserver(DestructionObserver *obs) { 131 void MessageLoop::AddDestructionObserver(DestructionObserver *obs) {
130 DCHECK(this == current()); 132 DCHECK(this == current());
131 destruction_observers_.AddObserver(obs); 133 destruction_observers_.AddObserver(obs);
132 } 134 }
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 // consequence!). 307 // consequence!).
306 return true; 308 return true;
307 } 309 }
308 310
309 // We couldn't run the task now because we're in a nested message loop 311 // We couldn't run the task now because we're in a nested message loop
310 // and the task isn't nestable. 312 // and the task isn't nestable.
311 deferred_non_nestable_work_queue_.push(pending_task); 313 deferred_non_nestable_work_queue_.push(pending_task);
312 return false; 314 return false;
313 } 315 }
314 316
317 void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) {
318 // Move to the delayed work queue. Initialize the sequence number
319 // before inserting into the delayed_work_queue_. The sequence number
320 // is used to faciliate FIFO sorting when two tasks have the same
321 // delayed_run_time value.
322 PendingTask new_pending_task(pending_task);
323 new_pending_task.sequence_num = next_sequence_num_++;
324 delayed_work_queue_.push(new_pending_task);
325 }
326
315 void MessageLoop::ReloadWorkQueue() { 327 void MessageLoop::ReloadWorkQueue() {
316 // We can improve performance of our loading tasks from incoming_queue_ to 328 // We can improve performance of our loading tasks from incoming_queue_ to
317 // work_queue_ by waiting until the last minute (work_queue_ is empty) to 329 // work_queue_ by waiting until the last minute (work_queue_ is empty) to
318 // load. That reduces the number of locks-per-task significantly when our 330 // load. That reduces the number of locks-per-task significantly when our
319 // queues get large. 331 // queues get large.
320 if (!work_queue_.empty()) 332 if (!work_queue_.empty())
321 return; // Wait till we *really* need to lock and load. 333 return; // Wait till we *really* need to lock and load.
322 334
323 // Acquire all we can from the inter-thread queue with one lock acquisition. 335 // Acquire all we can from the inter-thread queue with one lock acquisition.
324 { 336 {
325 AutoLock lock(incoming_queue_lock_); 337 AutoLock lock(incoming_queue_lock_);
326 if (incoming_queue_.empty()) 338 if (incoming_queue_.empty())
327 return; 339 return;
328 std::swap(incoming_queue_, work_queue_); 340 std::swap(incoming_queue_, work_queue_);
329 DCHECK(incoming_queue_.empty()); 341 DCHECK(incoming_queue_.empty());
330 } 342 }
331 } 343 }
332 344
333 void MessageLoop::DeletePendingTasks() { 345 bool MessageLoop::DeletePendingTasks() {
334 /* Comment this out as it's causing crashes. 346 bool did_work = !work_queue_.empty();
335 while (!work_queue_.Empty()) { 347 while (!work_queue_.empty()) {
336 Task* task = work_queue_.Pop(); 348 PendingTask pending_task = work_queue_.front();
337 if (task->is_owned_by_message_loop()) 349 work_queue_.pop();
338 delete task; 350 if (!pending_task.delayed_run_time.is_null()) {
351 // We want to delete delayed tasks in the same order in which they would
352 // normally be deleted in case of any funny dependencies between delayed
353 // tasks.
354 AddToDelayedWorkQueue(pending_task);
355 } else {
356 // TODO(darin): Delete all tasks once it is safe to do so.
357 //delete task;
358 }
339 } 359 }
340 360 did_work |= !deferred_non_nestable_work_queue_.empty();
341 while (!delayed_non_nestable_queue_.Empty()) { 361 while (!deferred_non_nestable_work_queue_.empty()) {
342 Task* task = delayed_non_nestable_queue_.Pop(); 362 Task* task = deferred_non_nestable_work_queue_.front().task;
343 if (task->is_owned_by_message_loop()) 363 deferred_non_nestable_work_queue_.pop();
344 delete task; 364 // TODO(darin): Delete all tasks once it is safe to do so.
365 //delete task;
345 } 366 }
346 */ 367 did_work |= !delayed_work_queue_.empty();
368 while (!delayed_work_queue_.empty()) {
369 Task* task = delayed_work_queue_.top().task;
370 delayed_work_queue_.pop();
371 delete task;
372 }
373 return did_work;
347 } 374 }
348 375
349 bool MessageLoop::DoWork() { 376 bool MessageLoop::DoWork() {
350 if (!nestable_tasks_allowed_) { 377 if (!nestable_tasks_allowed_) {
351 // Task can't be executed right now. 378 // Task can't be executed right now.
352 return false; 379 return false;
353 } 380 }
354 381
355 for (;;) { 382 for (;;) {
356 ReloadWorkQueue(); 383 ReloadWorkQueue();
357 if (work_queue_.empty()) 384 if (work_queue_.empty())
358 break; 385 break;
359 386
360 // Execute oldest task. 387 // Execute oldest task.
361 do { 388 do {
362 PendingTask pending_task = work_queue_.front(); 389 PendingTask pending_task = work_queue_.front();
363 work_queue_.pop(); 390 work_queue_.pop();
364 if (!pending_task.delayed_run_time.is_null()) { 391 if (!pending_task.delayed_run_time.is_null()) {
365 bool was_empty = delayed_work_queue_.empty(); 392 bool was_empty = delayed_work_queue_.empty();
366 393 AddToDelayedWorkQueue(pending_task);
367 // Move to the delayed work queue. Initialize the sequence number
368 // before inserting into the delayed_work_queue_. The sequence number
369 // is used to faciliate FIFO sorting when two tasks have the same
370 // delayed_run_time value.
371 pending_task.sequence_num = next_sequence_num_++;
372 delayed_work_queue_.push(pending_task);
373
374 if (was_empty) // We only schedule the next delayed work item. 394 if (was_empty) // We only schedule the next delayed work item.
375 pump_->ScheduleDelayedWork(pending_task.delayed_run_time); 395 pump_->ScheduleDelayedWork(pending_task.delayed_run_time);
376 } else { 396 } else {
377 if (DeferOrRunPendingTask(pending_task)) 397 if (DeferOrRunPendingTask(pending_task))
378 return true; 398 return true;
379 } 399 }
380 } while (!work_queue_.empty()); 400 } while (!work_queue_.empty());
381 } 401 }
382 402
383 // Nothing happened. 403 // Nothing happened.
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 //------------------------------------------------------------------------------ 570 //------------------------------------------------------------------------------
551 // MessageLoopForIO 571 // MessageLoopForIO
552 572
553 #if defined(OS_WIN) 573 #if defined(OS_WIN)
554 574
555 void MessageLoopForIO::WatchObject(HANDLE object, Watcher* watcher) { 575 void MessageLoopForIO::WatchObject(HANDLE object, Watcher* watcher) {
556 pump_win()->WatchObject(object, watcher); 576 pump_win()->WatchObject(object, watcher);
557 } 577 }
558 578
559 #endif // defined(OS_WIN) 579 #endif // defined(OS_WIN)
OLDNEW
« no previous file with comments | « base/message_loop.h ('k') | base/message_loop_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698