| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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) |
| OLD | NEW |