| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 VALUE_TO_NUMBER_AND_NAME(kTaskRunEvent) | 84 VALUE_TO_NUMBER_AND_NAME(kTaskRunEvent) |
| 85 VALUE_TO_NUMBER_AND_NAME(kTimerEvent) | 85 VALUE_TO_NUMBER_AND_NAME(kTimerEvent) |
| 86 | 86 |
| 87 {-1, NULL} // The list must be null terminated, per API to histogram. | 87 {-1, NULL} // The list must be null terminated, per API to histogram. |
| 88 }; | 88 }; |
| 89 | 89 |
| 90 bool enable_histogrammer_ = false; | 90 bool enable_histogrammer_ = false; |
| 91 | 91 |
| 92 MessageLoop::MessagePumpFactory* message_pump_for_ui_factory_ = NULL; | 92 MessageLoop::MessagePumpFactory* message_pump_for_ui_factory_ = NULL; |
| 93 | 93 |
| 94 // Create a process-wide unique ID to represent this task in trace events. This |
| 95 // will be mangled with a Process ID hash to reduce the likelyhood of colliding |
| 96 // with MessageLoop pointers on other processes. |
| 97 uint64 GetTaskTraceID(const PendingTask& task, MessageLoop* loop) { |
| 98 return (static_cast<uint64>(task.sequence_num) << 32) | |
| 99 static_cast<uint64>(reinterpret_cast<intptr_t>(loop)); |
| 100 } |
| 101 |
| 94 } // namespace | 102 } // namespace |
| 95 | 103 |
| 96 //------------------------------------------------------------------------------ | 104 //------------------------------------------------------------------------------ |
| 97 | 105 |
| 98 #if defined(OS_WIN) | 106 #if defined(OS_WIN) |
| 99 | 107 |
| 100 // Upon a SEH exception in this thread, it restores the original unhandled | 108 // Upon a SEH exception in this thread, it restores the original unhandled |
| 101 // exception filter. | 109 // exception filter. |
| 102 static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) { | 110 static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) { |
| 103 ::SetUnhandledExceptionFilter(old_filter); | 111 ::SetUnhandledExceptionFilter(old_filter); |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 return false; | 435 return false; |
| 428 | 436 |
| 429 PendingTask pending_task = deferred_non_nestable_work_queue_.front(); | 437 PendingTask pending_task = deferred_non_nestable_work_queue_.front(); |
| 430 deferred_non_nestable_work_queue_.pop(); | 438 deferred_non_nestable_work_queue_.pop(); |
| 431 | 439 |
| 432 RunTask(pending_task); | 440 RunTask(pending_task); |
| 433 return true; | 441 return true; |
| 434 } | 442 } |
| 435 | 443 |
| 436 void MessageLoop::RunTask(const PendingTask& pending_task) { | 444 void MessageLoop::RunTask(const PendingTask& pending_task) { |
| 445 TRACE_EVENT_FLOW_END0("task", "MessageLoop::PostTask", |
| 446 TRACE_ID_MANGLE(GetTaskTraceID(pending_task, this))); |
| 437 TRACE_EVENT2("task", "MessageLoop::RunTask", | 447 TRACE_EVENT2("task", "MessageLoop::RunTask", |
| 438 "src_file", pending_task.posted_from.file_name(), | 448 "src_file", pending_task.posted_from.file_name(), |
| 439 "src_func", pending_task.posted_from.function_name()); | 449 "src_func", pending_task.posted_from.function_name()); |
| 440 DCHECK(nestable_tasks_allowed_); | 450 DCHECK(nestable_tasks_allowed_); |
| 441 // Execute the task and assume the worst: It is probably not reentrant. | 451 // Execute the task and assume the worst: It is probably not reentrant. |
| 442 nestable_tasks_allowed_ = false; | 452 nestable_tasks_allowed_ = false; |
| 443 | 453 |
| 444 // Before running the task, store the program counter where it was posted | 454 // Before running the task, store the program counter where it was posted |
| 445 // and deliberately alias it to ensure it is on the stack if the task | 455 // and deliberately alias it to ensure it is on the stack if the task |
| 446 // crashes. Be careful not to assume that the variable itself will have the | 456 // crashes. Be careful not to assume that the variable itself will have the |
| (...skipping 28 matching lines...) Expand all Loading... |
| 475 return true; | 485 return true; |
| 476 } | 486 } |
| 477 | 487 |
| 478 // We couldn't run the task now because we're in a nested message loop | 488 // We couldn't run the task now because we're in a nested message loop |
| 479 // and the task isn't nestable. | 489 // and the task isn't nestable. |
| 480 deferred_non_nestable_work_queue_.push(pending_task); | 490 deferred_non_nestable_work_queue_.push(pending_task); |
| 481 return false; | 491 return false; |
| 482 } | 492 } |
| 483 | 493 |
| 484 void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) { | 494 void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) { |
| 485 // Move to the delayed work queue. Initialize the sequence number | 495 // Move to the delayed work queue. |
| 486 // before inserting into the delayed_work_queue_. The sequence number | 496 delayed_work_queue_.push(pending_task); |
| 487 // is used to faciliate FIFO sorting when two tasks have the same | |
| 488 // delayed_run_time value. | |
| 489 PendingTask new_pending_task(pending_task); | |
| 490 new_pending_task.sequence_num = next_sequence_num_++; | |
| 491 delayed_work_queue_.push(new_pending_task); | |
| 492 } | 497 } |
| 493 | 498 |
| 494 void MessageLoop::ReloadWorkQueue() { | 499 void MessageLoop::ReloadWorkQueue() { |
| 495 // We can improve performance of our loading tasks from incoming_queue_ to | 500 // We can improve performance of our loading tasks from incoming_queue_ to |
| 496 // work_queue_ by waiting until the last minute (work_queue_ is empty) to | 501 // work_queue_ by waiting until the last minute (work_queue_ is empty) to |
| 497 // load. That reduces the number of locks-per-task significantly when our | 502 // load. That reduces the number of locks-per-task significantly when our |
| 498 // queues get large. | 503 // queues get large. |
| 499 if (!work_queue_.empty()) | 504 if (!work_queue_.empty()) |
| 500 return; // Wait till we *really* need to lock and load. | 505 return; // Wait till we *really* need to lock and load. |
| 501 | 506 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 // Possibly called on a background thread! | 584 // Possibly called on a background thread! |
| 580 void MessageLoop::AddToIncomingQueue(PendingTask* pending_task) { | 585 void MessageLoop::AddToIncomingQueue(PendingTask* pending_task) { |
| 581 // Warning: Don't try to short-circuit, and handle this thread's tasks more | 586 // Warning: Don't try to short-circuit, and handle this thread's tasks more |
| 582 // directly, as it could starve handling of foreign threads. Put every task | 587 // directly, as it could starve handling of foreign threads. Put every task |
| 583 // into this queue. | 588 // into this queue. |
| 584 | 589 |
| 585 scoped_refptr<base::MessagePump> pump; | 590 scoped_refptr<base::MessagePump> pump; |
| 586 { | 591 { |
| 587 base::AutoLock locked(incoming_queue_lock_); | 592 base::AutoLock locked(incoming_queue_lock_); |
| 588 | 593 |
| 594 // Initialize the sequence number. The sequence number is used for delayed |
| 595 // tasks (to faciliate FIFO sorting when two tasks have the same |
| 596 // delayed_run_time value) and for identifying the task in about:tracing. |
| 597 pending_task->sequence_num = next_sequence_num_++; |
| 598 |
| 599 TRACE_EVENT_FLOW_BEGIN0("task", "MessageLoop::PostTask", |
| 600 TRACE_ID_MANGLE(GetTaskTraceID(*pending_task, this))); |
| 601 |
| 589 bool was_empty = incoming_queue_.empty(); | 602 bool was_empty = incoming_queue_.empty(); |
| 590 incoming_queue_.push(*pending_task); | 603 incoming_queue_.push(*pending_task); |
| 591 pending_task->task.Reset(); | 604 pending_task->task.Reset(); |
| 592 if (!was_empty) | 605 if (!was_empty) |
| 593 return; // Someone else should have started the sub-pump. | 606 return; // Someone else should have started the sub-pump. |
| 594 | 607 |
| 595 pump = pump_; | 608 pump = pump_; |
| 596 } | 609 } |
| 597 // Since the incoming_queue_ may contain a task that destroys this message | 610 // Since the incoming_queue_ may contain a task that destroys this message |
| 598 // loop, we cannot exit incoming_queue_lock_ until we are done with |this|. | 611 // loop, we cannot exit incoming_queue_lock_ until we are done with |this|. |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 768 Watcher *delegate) { | 781 Watcher *delegate) { |
| 769 return pump_libevent()->WatchFileDescriptor( | 782 return pump_libevent()->WatchFileDescriptor( |
| 770 fd, | 783 fd, |
| 771 persistent, | 784 persistent, |
| 772 static_cast<base::MessagePumpLibevent::Mode>(mode), | 785 static_cast<base::MessagePumpLibevent::Mode>(mode), |
| 773 controller, | 786 controller, |
| 774 delegate); | 787 delegate); |
| 775 } | 788 } |
| 776 | 789 |
| 777 #endif | 790 #endif |
| OLD | NEW |