| Index: base/message_loop.cc
|
| diff --git a/base/message_loop.cc b/base/message_loop.cc
|
| index eec8a2429b2bd0c4662ec65a9c8c27e3572ff717..e74331ac386a12faa9f162ba552e788366602273 100644
|
| --- a/base/message_loop.cc
|
| +++ b/base/message_loop.cc
|
| @@ -113,14 +113,6 @@ MessageLoop::DestructionObserver::~DestructionObserver() {
|
|
|
| //------------------------------------------------------------------------------
|
|
|
| -// static
|
| -MessageLoop* MessageLoop::current() {
|
| - // TODO(darin): sadly, we cannot enable this yet since people call us even
|
| - // when they have no intention of using us.
|
| - // DCHECK(loop) << "Ouch, did you forget to initialize me?";
|
| - return lazy_tls_ptr.Pointer()->Get();
|
| -}
|
| -
|
| MessageLoop::MessageLoop(Type type)
|
| : type_(type),
|
| nestable_tasks_allowed_(true),
|
| @@ -192,6 +184,19 @@ MessageLoop::~MessageLoop() {
|
| lazy_tls_ptr.Pointer()->Set(NULL);
|
| }
|
|
|
| +// static
|
| +MessageLoop* MessageLoop::current() {
|
| + // TODO(darin): sadly, we cannot enable this yet since people call us even
|
| + // when they have no intention of using us.
|
| + // DCHECK(loop) << "Ouch, did you forget to initialize me?";
|
| + return lazy_tls_ptr.Pointer()->Get();
|
| +}
|
| +
|
| +// static
|
| +void MessageLoop::EnableHistogrammer(bool enable) {
|
| + enable_histogrammer_ = enable;
|
| +}
|
| +
|
| void MessageLoop::AddDestructionObserver(
|
| DestructionObserver* destruction_observer) {
|
| DCHECK_EQ(this, current());
|
| @@ -204,14 +209,24 @@ void MessageLoop::RemoveDestructionObserver(
|
| destruction_observers_.RemoveObserver(destruction_observer);
|
| }
|
|
|
| -void MessageLoop::AddTaskObserver(TaskObserver* task_observer) {
|
| - DCHECK_EQ(this, current());
|
| - task_observers_.AddObserver(task_observer);
|
| +void MessageLoop::PostTask(
|
| + const tracked_objects::Location& from_here, Task* task) {
|
| + PostTask_Helper(from_here, task, 0, true);
|
| }
|
|
|
| -void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) {
|
| - DCHECK_EQ(this, current());
|
| - task_observers_.RemoveObserver(task_observer);
|
| +void MessageLoop::PostDelayedTask(
|
| + const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
|
| + PostTask_Helper(from_here, task, delay_ms, true);
|
| +}
|
| +
|
| +void MessageLoop::PostNonNestableTask(
|
| + const tracked_objects::Location& from_here, Task* task) {
|
| + PostTask_Helper(from_here, task, 0, false);
|
| +}
|
| +
|
| +void MessageLoop::PostNonNestableDelayedTask(
|
| + const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
|
| + PostTask_Helper(from_here, task, delay_ms, false);
|
| }
|
|
|
| void MessageLoop::Run() {
|
| @@ -225,6 +240,54 @@ void MessageLoop::RunAllPending() {
|
| RunHandler();
|
| }
|
|
|
| +void MessageLoop::Quit() {
|
| + DCHECK_EQ(this, current());
|
| + if (state_) {
|
| + state_->quit_received = true;
|
| + } else {
|
| + NOTREACHED() << "Must be inside Run to call Quit";
|
| + }
|
| +}
|
| +
|
| +void MessageLoop::QuitNow() {
|
| + DCHECK_EQ(this, current());
|
| + if (state_) {
|
| + pump_->Quit();
|
| + } else {
|
| + NOTREACHED() << "Must be inside Run to call Quit";
|
| + }
|
| +}
|
| +
|
| +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();
|
| + }
|
| +}
|
| +
|
| +bool MessageLoop::NestableTasksAllowed() const {
|
| + return nestable_tasks_allowed_;
|
| +}
|
| +
|
| +bool MessageLoop::IsNested() {
|
| + return state_->run_depth > 1;
|
| +}
|
| +
|
| +void MessageLoop::AddTaskObserver(TaskObserver* task_observer) {
|
| + DCHECK_EQ(this, current());
|
| + task_observers_.AddObserver(task_observer);
|
| +}
|
| +
|
| +void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) {
|
| + DCHECK_EQ(this, current());
|
| + task_observers_.RemoveObserver(task_observer);
|
| +}
|
| +
|
| +//------------------------------------------------------------------------------
|
| +
|
| // Runs the loop in two different SEH modes:
|
| // enable_SEH_restoration_ = false : any unhandled exception goes to the last
|
| // one that calls SetUnhandledExceptionFilter().
|
| @@ -240,7 +303,7 @@ void MessageLoop::RunHandler() {
|
|
|
| RunInternal();
|
| }
|
| -//------------------------------------------------------------------------------
|
| +
|
| #if defined(OS_WIN)
|
| __declspec(noinline) void MessageLoop::RunInternalInSEHFrame() {
|
| LPTOP_LEVEL_EXCEPTION_FILTER current_filter = GetTopSEHFilter();
|
| @@ -251,7 +314,6 @@ __declspec(noinline) void MessageLoop::RunInternalInSEHFrame() {
|
| return;
|
| }
|
| #endif
|
| -//------------------------------------------------------------------------------
|
|
|
| void MessageLoop::RunInternal() {
|
| DCHECK_EQ(this, current());
|
| @@ -269,9 +331,6 @@ void MessageLoop::RunInternal() {
|
| pump_->Run(this);
|
| }
|
|
|
| -//------------------------------------------------------------------------------
|
| -// Wrapper functions for use in above message loop framework.
|
| -
|
| bool MessageLoop::ProcessNextDelayedNonNestableTask() {
|
| if (state_->run_depth != 1)
|
| return false;
|
| @@ -286,130 +345,6 @@ bool MessageLoop::ProcessNextDelayedNonNestableTask() {
|
| return true;
|
| }
|
|
|
| -//------------------------------------------------------------------------------
|
| -
|
| -void MessageLoop::Quit() {
|
| - DCHECK_EQ(this, current());
|
| - if (state_) {
|
| - state_->quit_received = true;
|
| - } else {
|
| - NOTREACHED() << "Must be inside Run to call Quit";
|
| - }
|
| -}
|
| -
|
| -void MessageLoop::QuitNow() {
|
| - DCHECK_EQ(this, current());
|
| - if (state_) {
|
| - pump_->Quit();
|
| - } else {
|
| - NOTREACHED() << "Must be inside Run to call Quit";
|
| - }
|
| -}
|
| -
|
| -void MessageLoop::PostTask(
|
| - const tracked_objects::Location& from_here, Task* task) {
|
| - PostTask_Helper(from_here, task, 0, true);
|
| -}
|
| -
|
| -void MessageLoop::PostDelayedTask(
|
| - const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
|
| - PostTask_Helper(from_here, task, delay_ms, true);
|
| -}
|
| -
|
| -void MessageLoop::PostNonNestableTask(
|
| - const tracked_objects::Location& from_here, Task* task) {
|
| - PostTask_Helper(from_here, task, 0, false);
|
| -}
|
| -
|
| -void MessageLoop::PostNonNestableDelayedTask(
|
| - const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
|
| - PostTask_Helper(from_here, task, delay_ms, false);
|
| -}
|
| -
|
| -// Possibly called on a background thread!
|
| -void MessageLoop::PostTask_Helper(
|
| - const tracked_objects::Location& from_here, Task* task, int64 delay_ms,
|
| - bool nestable) {
|
| - task->SetBirthPlace(from_here);
|
| -
|
| - PendingTask pending_task(task, nestable);
|
| -
|
| - if (delay_ms > 0) {
|
| - pending_task.delayed_run_time =
|
| - TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms);
|
| -
|
| -#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_ms < (2 * base::Time::kMinLowResolutionThresholdMs);
|
| - if (needs_high_res_timers) {
|
| - base::Time::ActivateHighResolutionTimer(true);
|
| - high_resolution_timer_expiration_ = TimeTicks::Now() +
|
| - TimeDelta::FromMilliseconds(kHighResolutionTimerModeLeaseTimeMs);
|
| - }
|
| - }
|
| -#endif
|
| - } else {
|
| - DCHECK_EQ(delay_ms, 0) << "delay should not be negative";
|
| - }
|
| -
|
| -#if defined(OS_WIN)
|
| - if (!high_resolution_timer_expiration_.is_null()) {
|
| - if (TimeTicks::Now() > high_resolution_timer_expiration_) {
|
| - base::Time::ActivateHighResolutionTimer(false);
|
| - high_resolution_timer_expiration_ = TimeTicks();
|
| - }
|
| - }
|
| -#endif
|
| -
|
| - // 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<base::MessagePump> pump;
|
| - {
|
| - AutoLock locked(incoming_queue_lock_);
|
| -
|
| - bool was_empty = incoming_queue_.empty();
|
| - incoming_queue_.push(pending_task);
|
| - if (!was_empty)
|
| - return; // 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();
|
| -}
|
| -
|
| -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();
|
| - }
|
| -}
|
| -
|
| -bool MessageLoop::NestableTasksAllowed() const {
|
| - return nestable_tasks_allowed_;
|
| -}
|
| -
|
| -bool MessageLoop::IsNested() {
|
| - return state_->run_depth > 1;
|
| -}
|
| -
|
| -//------------------------------------------------------------------------------
|
| -
|
| void MessageLoop::RunTask(Task* task) {
|
| DCHECK(nestable_tasks_allowed_);
|
| // Execute the task and assume the worst: It is probably not reentrant.
|
| @@ -513,6 +448,92 @@ bool MessageLoop::DeletePendingTasks() {
|
| return did_work;
|
| }
|
|
|
| +// Possibly called on a background thread!
|
| +void MessageLoop::PostTask_Helper(
|
| + const tracked_objects::Location& from_here, Task* task, int64 delay_ms,
|
| + bool nestable) {
|
| + task->SetBirthPlace(from_here);
|
| +
|
| + PendingTask pending_task(task, nestable);
|
| +
|
| + if (delay_ms > 0) {
|
| + pending_task.delayed_run_time =
|
| + TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms);
|
| +
|
| +#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_ms < (2 * base::Time::kMinLowResolutionThresholdMs);
|
| + if (needs_high_res_timers) {
|
| + base::Time::ActivateHighResolutionTimer(true);
|
| + high_resolution_timer_expiration_ = TimeTicks::Now() +
|
| + TimeDelta::FromMilliseconds(kHighResolutionTimerModeLeaseTimeMs);
|
| + }
|
| + }
|
| +#endif
|
| + } else {
|
| + DCHECK_EQ(delay_ms, 0) << "delay should not be negative";
|
| + }
|
| +
|
| +#if defined(OS_WIN)
|
| + if (!high_resolution_timer_expiration_.is_null()) {
|
| + if (TimeTicks::Now() > high_resolution_timer_expiration_) {
|
| + base::Time::ActivateHighResolutionTimer(false);
|
| + high_resolution_timer_expiration_ = TimeTicks();
|
| + }
|
| + }
|
| +#endif
|
| +
|
| + // 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<base::MessagePump> pump;
|
| + {
|
| + AutoLock locked(incoming_queue_lock_);
|
| +
|
| + bool was_empty = incoming_queue_.empty();
|
| + incoming_queue_.push(pending_task);
|
| + if (!was_empty)
|
| + return; // 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();
|
| +}
|
| +
|
| +//------------------------------------------------------------------------------
|
| +// Method and data for histogramming events and actions taken by each instance
|
| +// on each thread.
|
| +
|
| +void MessageLoop::StartHistogrammer() {
|
| + if (enable_histogrammer_ && !message_histogram_.get()
|
| + && base::StatisticsRecorder::IsActive()) {
|
| + DCHECK(!thread_name_.empty());
|
| + message_histogram_ = base::LinearHistogram::FactoryGet(
|
| + "MsgLoop:" + thread_name_,
|
| + kLeastNonZeroMessageId, kMaxMessageId,
|
| + kNumberOfDistinctMessagesDisplayed,
|
| + message_histogram_->kHexRangePrintingFlag);
|
| + message_histogram_->SetRangeDescriptions(event_descriptions_);
|
| + }
|
| +}
|
| +
|
| +void MessageLoop::HistogramEvent(int event) {
|
| + if (message_histogram_.get())
|
| + message_histogram_->Add(event);
|
| +}
|
| +
|
| bool MessageLoop::DoWork() {
|
| if (!nestable_tasks_allowed_) {
|
| // Task can't be executed right now.
|
| @@ -629,33 +650,6 @@ bool MessageLoop::PendingTask::operator<(const PendingTask& other) const {
|
| }
|
|
|
| //------------------------------------------------------------------------------
|
| -// Method and data for histogramming events and actions taken by each instance
|
| -// on each thread.
|
| -
|
| -// static
|
| -void MessageLoop::EnableHistogrammer(bool enable) {
|
| - enable_histogrammer_ = enable;
|
| -}
|
| -
|
| -void MessageLoop::StartHistogrammer() {
|
| - if (enable_histogrammer_ && !message_histogram_.get()
|
| - && base::StatisticsRecorder::IsActive()) {
|
| - DCHECK(!thread_name_.empty());
|
| - message_histogram_ = base::LinearHistogram::FactoryGet(
|
| - "MsgLoop:" + thread_name_,
|
| - kLeastNonZeroMessageId, kMaxMessageId,
|
| - kNumberOfDistinctMessagesDisplayed,
|
| - message_histogram_->kHexRangePrintingFlag);
|
| - message_histogram_->SetRangeDescriptions(event_descriptions_);
|
| - }
|
| -}
|
| -
|
| -void MessageLoop::HistogramEvent(int event) {
|
| - if (message_histogram_.get())
|
| - message_histogram_->Add(event);
|
| -}
|
| -
|
| -//------------------------------------------------------------------------------
|
| // MessageLoopForUI
|
|
|
| #if defined(OS_WIN)
|
|
|