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 |