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; |