| Index: base/message_loop/message_loop.cc
|
| diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
|
| index 4e0c5f6801e9e15d36a5e7d220d0b956ff91f7a9..3b9badd1826b3656fbb311bce1d247c6b6abcdbf 100644
|
| --- a/base/message_loop/message_loop.cc
|
| +++ b/base/message_loop/message_loop.cc
|
| @@ -89,14 +89,6 @@ bool enable_histogrammer_ = false;
|
|
|
| MessageLoop::MessagePumpFactory* message_pump_for_ui_factory_ = NULL;
|
|
|
| -// Create a process-wide unique ID to represent this task in trace events. This
|
| -// will be mangled with a Process ID hash to reduce the likelyhood of colliding
|
| -// with MessageLoop pointers on other processes.
|
| -uint64 GetTaskTraceID(const PendingTask& task, MessageLoop* loop) {
|
| - return (static_cast<uint64>(task.sequence_num) << 32) |
|
| - static_cast<uint64>(reinterpret_cast<intptr_t>(loop));
|
| -}
|
| -
|
| } // namespace
|
|
|
| //------------------------------------------------------------------------------
|
| @@ -139,11 +131,10 @@ MessageLoop::MessageLoop(Type type)
|
| nestable_tasks_allowed_(true),
|
| exception_restoration_(false),
|
| message_histogram_(NULL),
|
| - run_loop_(NULL),
|
| #if defined(OS_WIN)
|
| os_modal_loop_(false),
|
| #endif // OS_WIN
|
| - next_sequence_num_(0) {
|
| + run_loop_(NULL) {
|
| DCHECK(!current()) << "should only have one message loop per thread";
|
| lazy_tls_ptr.Pointer()->Set(this);
|
|
|
| @@ -167,7 +158,7 @@ MessageLoop::MessageLoop(Type type)
|
| #define MESSAGE_PUMP_UI NULL
|
| // ipc_channel_nacl.cc uses a worker thread to do socket reads currently, and
|
| // doesn't require extra support for watching file descriptors.
|
| -#define MESSAGE_PUMP_IO new MessagePumpDefault();
|
| +#define MESSAGE_PUMP_IO new MessagePumpDefault()
|
| #elif defined(OS_POSIX) // POSIX but not MACOSX.
|
| #define MESSAGE_PUMP_UI new MessagePumpForUI()
|
| #define MESSAGE_PUMP_IO new MessagePumpLibevent()
|
| @@ -177,14 +168,14 @@ MessageLoop::MessageLoop(Type type)
|
|
|
| if (type_ == TYPE_UI) {
|
| if (message_pump_for_ui_factory_)
|
| - pump_ = message_pump_for_ui_factory_();
|
| + pump_.reset(message_pump_for_ui_factory_());
|
| else
|
| - pump_ = MESSAGE_PUMP_UI;
|
| + pump_.reset(MESSAGE_PUMP_UI);
|
| } else if (type_ == TYPE_IO) {
|
| - pump_ = MESSAGE_PUMP_IO;
|
| + pump_.reset(MESSAGE_PUMP_IO);
|
| } else {
|
| DCHECK_EQ(TYPE_DEFAULT, type_);
|
| - pump_ = new MessagePumpDefault();
|
| + pump_.reset(new MessagePumpDefault());
|
| }
|
| }
|
|
|
| @@ -202,7 +193,7 @@ MessageLoop::~MessageLoop() {
|
| bool did_work;
|
| for (int i = 0; i < 100; ++i) {
|
| DeletePendingTasks();
|
| - ReloadWorkQueue();
|
| + message_loop_proxy_->ReloadWorkQueue(&work_queue_);
|
| // If we end up with empty queues, then break out of the loop.
|
| did_work = DeletePendingTasks();
|
| if (!did_work)
|
| @@ -223,16 +214,6 @@ MessageLoop::~MessageLoop() {
|
|
|
| // OK, now make it so that no one can find us.
|
| lazy_tls_ptr.Pointer()->Set(NULL);
|
| -
|
| -#if defined(OS_WIN)
|
| - // If we left the high-resolution timer activated, deactivate it now.
|
| - // Doing this is not-critical, it is mainly to make sure we track
|
| - // the high resolution timer activations properly in our unit tests.
|
| - if (!high_resolution_timer_expiration_.is_null()) {
|
| - Time::ActivateHighResolutionTimer(false);
|
| - high_resolution_timer_expiration_ = TimeTicks();
|
| - }
|
| -#endif
|
| }
|
|
|
| // static
|
| @@ -273,18 +254,14 @@ void MessageLoop::PostTask(
|
| const tracked_objects::Location& from_here,
|
| const Closure& task) {
|
| DCHECK(!task.is_null()) << from_here.ToString();
|
| - PendingTask pending_task(
|
| - from_here, task, CalculateDelayedRuntime(TimeDelta()), true);
|
| - AddToIncomingQueue(&pending_task, false);
|
| + message_loop_proxy_->AddToIncomingQueue(from_here, task, TimeDelta(), true);
|
| }
|
|
|
| bool MessageLoop::TryPostTask(
|
| const tracked_objects::Location& from_here,
|
| const Closure& task) {
|
| DCHECK(!task.is_null()) << from_here.ToString();
|
| - PendingTask pending_task(
|
| - from_here, task, CalculateDelayedRuntime(TimeDelta()), true);
|
| - return AddToIncomingQueue(&pending_task, true);
|
| + return message_loop_proxy_->TryAddToIncomingQueue(from_here, task);
|
| }
|
|
|
| void MessageLoop::PostDelayedTask(
|
| @@ -292,18 +269,14 @@ void MessageLoop::PostDelayedTask(
|
| const Closure& task,
|
| TimeDelta delay) {
|
| DCHECK(!task.is_null()) << from_here.ToString();
|
| - PendingTask pending_task(
|
| - from_here, task, CalculateDelayedRuntime(delay), true);
|
| - AddToIncomingQueue(&pending_task, false);
|
| + message_loop_proxy_->AddToIncomingQueue(from_here, task, delay, true);
|
| }
|
|
|
| void MessageLoop::PostNonNestableTask(
|
| const tracked_objects::Location& from_here,
|
| const Closure& task) {
|
| DCHECK(!task.is_null()) << from_here.ToString();
|
| - PendingTask pending_task(
|
| - from_here, task, CalculateDelayedRuntime(TimeDelta()), false);
|
| - AddToIncomingQueue(&pending_task, false);
|
| + message_loop_proxy_->AddToIncomingQueue(from_here, task, TimeDelta(), false);
|
| }
|
|
|
| void MessageLoop::PostNonNestableDelayedTask(
|
| @@ -311,9 +284,7 @@ void MessageLoop::PostNonNestableDelayedTask(
|
| const Closure& task,
|
| TimeDelta delay) {
|
| DCHECK(!task.is_null()) << from_here.ToString();
|
| - PendingTask pending_task(
|
| - from_here, task, CalculateDelayedRuntime(delay), false);
|
| - AddToIncomingQueue(&pending_task, false);
|
| + message_loop_proxy_->AddToIncomingQueue(from_here, task, delay, false);
|
| }
|
|
|
| void MessageLoop::Run() {
|
| @@ -357,13 +328,17 @@ Closure MessageLoop::QuitWhenIdleClosure() {
|
| return Bind(&QuitCurrentWhenIdle);
|
| }
|
|
|
| +scoped_refptr<MessageLoopProxy> MessageLoop::message_loop_proxy() {
|
| + return message_loop_proxy_;
|
| +}
|
| +
|
| void MessageLoop::SetNestableTasksAllowed(bool allowed) {
|
| if (nestable_tasks_allowed_ != allowed) {
|
| nestable_tasks_allowed_ = allowed;
|
| if (!nestable_tasks_allowed_)
|
| return;
|
| // Start the native pump if we are not already pumping.
|
| - pump_->ScheduleWork();
|
| + StartPump();
|
| }
|
| }
|
|
|
| @@ -385,17 +360,21 @@ void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) {
|
| task_observers_.RemoveObserver(task_observer);
|
| }
|
|
|
| -void MessageLoop::AssertIdle() const {
|
| - // We only check |incoming_queue_|, since we don't want to lock |work_queue_|.
|
| - AutoLock lock(incoming_queue_lock_);
|
| - DCHECK(incoming_queue_.empty());
|
| -}
|
| -
|
| bool MessageLoop::is_running() const {
|
| DCHECK_EQ(this, current());
|
| return run_loop_ != NULL;
|
| }
|
|
|
| +bool MessageLoop::IsHishResolutionTimersEnabledForTest() {
|
| + return message_loop_proxy_->IsHishResolutionTimersEnabledForTest();
|
| +}
|
| +
|
| +bool MessageLoop::IsIdleForTest() {
|
| + // We only check the imcoming queue|, since we don't want to lock the work
|
| + // queue.
|
| + return message_loop_proxy_->IsIdleForTest();
|
| +}
|
| +
|
| //------------------------------------------------------------------------------
|
|
|
| // Runs the loop in two different SEH modes:
|
| @@ -457,7 +436,7 @@ bool MessageLoop::ProcessNextDelayedNonNestableTask() {
|
|
|
| void MessageLoop::RunTask(const PendingTask& pending_task) {
|
| TRACE_EVENT_FLOW_END0("task", "MessageLoop::PostTask",
|
| - TRACE_ID_MANGLE(GetTaskTraceID(pending_task, this)));
|
| + TRACE_ID_MANGLE(GetTaskTraceID(pending_task)));
|
| TRACE_EVENT2("task", "MessageLoop::RunTask",
|
| "src_file", pending_task.posted_from.file_name(),
|
| "src_func", pending_task.posted_from.function_name());
|
| @@ -510,24 +489,6 @@ void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) {
|
| delayed_work_queue_.push(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
|
| - // load. That reduces the number of locks-per-task significantly when our
|
| - // queues get large.
|
| - if (!work_queue_.empty())
|
| - return; // Wait till we *really* need to lock and load.
|
| -
|
| - // Acquire all we can from the inter-thread queue with one lock acquisition.
|
| - {
|
| - AutoLock lock(incoming_queue_lock_);
|
| - if (incoming_queue_.empty())
|
| - return;
|
| - incoming_queue_.Swap(&work_queue_); // Constant time
|
| - DCHECK(incoming_queue_.empty());
|
| - }
|
| -}
|
| -
|
| bool MessageLoop::DeletePendingTasks() {
|
| bool did_work = !work_queue_.empty();
|
| while (!work_queue_.empty()) {
|
| @@ -557,85 +518,13 @@ bool MessageLoop::DeletePendingTasks() {
|
| return did_work;
|
| }
|
|
|
| -TimeTicks MessageLoop::CalculateDelayedRuntime(TimeDelta delay) {
|
| - TimeTicks delayed_run_time;
|
| - if (delay > TimeDelta()) {
|
| - delayed_run_time = TimeTicks::Now() + delay;
|
| -
|
| -#if defined(OS_WIN)
|
| - if (high_resolution_timer_expiration_.is_null()) {
|
| - // Windows timers are granular to 15.6ms. If we only set high-res
|
| - // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms,
|
| - // which as a percentage is pretty inaccurate. So enable high
|
| - // res timers for any timer which is within 2x of the granularity.
|
| - // This is a tradeoff between accuracy and power management.
|
| - bool needs_high_res_timers = delay.InMilliseconds() <
|
| - (2 * Time::kMinLowResolutionThresholdMs);
|
| - if (needs_high_res_timers) {
|
| - if (Time::ActivateHighResolutionTimer(true)) {
|
| - high_resolution_timer_expiration_ = TimeTicks::Now() +
|
| - TimeDelta::FromMilliseconds(kHighResolutionTimerModeLeaseTimeMs);
|
| - }
|
| - }
|
| - }
|
| -#endif
|
| - } else {
|
| - DCHECK_EQ(delay.InMilliseconds(), 0) << "delay should not be negative";
|
| - }
|
| -
|
| -#if defined(OS_WIN)
|
| - if (!high_resolution_timer_expiration_.is_null()) {
|
| - if (TimeTicks::Now() > high_resolution_timer_expiration_) {
|
| - Time::ActivateHighResolutionTimer(false);
|
| - high_resolution_timer_expiration_ = TimeTicks();
|
| - }
|
| - }
|
| -#endif
|
| -
|
| - return delayed_run_time;
|
| +void MessageLoop::StartPump() {
|
| + pump_->ScheduleWork();
|
| }
|
|
|
| -// Possibly called on a background thread!
|
| -bool MessageLoop::AddToIncomingQueue(PendingTask* pending_task,
|
| - bool use_try_lock) {
|
| - // Warning: Don't try to short-circuit, and handle this thread's tasks more
|
| - // directly, as it could starve handling of foreign threads. Put every task
|
| - // into this queue.
|
| -
|
| - scoped_refptr<MessagePump> pump;
|
| - {
|
| - if (use_try_lock) {
|
| - if (!incoming_queue_lock_.Try()) {
|
| - pending_task->task.Reset();
|
| - return false;
|
| - }
|
| - } else {
|
| - incoming_queue_lock_.Acquire();
|
| - }
|
| - AutoLock locked(incoming_queue_lock_, AutoLock::AlreadyAcquired());
|
| - // Initialize the sequence number. The sequence number is used for delayed
|
| - // tasks (to faciliate FIFO sorting when two tasks have the same
|
| - // delayed_run_time value) and for identifying the task in about:tracing.
|
| - pending_task->sequence_num = next_sequence_num_++;
|
| -
|
| - TRACE_EVENT_FLOW_BEGIN0("task", "MessageLoop::PostTask",
|
| - TRACE_ID_MANGLE(GetTaskTraceID(*pending_task, this)));
|
| -
|
| - bool was_empty = incoming_queue_.empty();
|
| - incoming_queue_.push(*pending_task);
|
| - pending_task->task.Reset();
|
| - if (!was_empty)
|
| - return true; // Someone else should have started the sub-pump.
|
| -
|
| - pump = pump_;
|
| - }
|
| - // Since the incoming_queue_ may contain a task that destroys this message
|
| - // loop, we cannot exit incoming_queue_lock_ until we are done with |this|.
|
| - // We use a stack-based reference to the message pump so that we can call
|
| - // ScheduleWork outside of incoming_queue_lock_.
|
| -
|
| - pump->ScheduleWork();
|
| - return true;
|
| +uint64 MessageLoop::GetTaskTraceID(const PendingTask& task) {
|
| + return (static_cast<uint64>(task.sequence_num) << 32) |
|
| + static_cast<uint64>(reinterpret_cast<intptr_t>(this));
|
| }
|
|
|
| //------------------------------------------------------------------------------
|
| @@ -671,7 +560,7 @@ bool MessageLoop::DoWork() {
|
| }
|
|
|
| for (;;) {
|
| - ReloadWorkQueue();
|
| + message_loop_proxy_->ReloadWorkQueue(&work_queue_);
|
| if (work_queue_.empty())
|
| break;
|
|
|
|
|