Chromium Code Reviews| Index: base/message_loop.cc |
| diff --git a/base/message_loop.cc b/base/message_loop.cc |
| index b040ecc8a6bf5f9bdde0d8229bfe493a5afd5a65..9f488e313ff8e7a637e4e99b377601c0d68c4cc1 100644 |
| --- a/base/message_loop.cc |
| +++ b/base/message_loop.cc |
| @@ -131,7 +131,6 @@ MessageLoop::MessageLoop(Type type) |
| nestable_tasks_allowed_(true), |
| exception_restoration_(false), |
| message_histogram_(NULL), |
| - state_(NULL), |
| #ifdef OS_WIN |
| os_modal_loop_(false), |
| #endif // OS_WIN |
| @@ -180,7 +179,7 @@ MessageLoop::MessageLoop(Type type) |
| MessageLoop::~MessageLoop() { |
| DCHECK_EQ(this, current()); |
| - DCHECK(!state_); |
| + DCHECK(!run_loop_); |
| // Clean up any unprocessed tasks, but take care: deleting a task could |
| // result in the addition of more tasks (e.g., via DeleteSoon). We set a |
| @@ -292,21 +291,89 @@ void MessageLoop::PostNonNestableDelayedTask( |
| AddToIncomingQueue(&pending_task); |
| } |
| +MessageLoop::RunLoop::RunLoop() |
| + : loop_(MessageLoop::current()), |
| + run_called_(false), |
| + stop_called_(false), |
| + running_(false), |
| + run_depth_(0), |
| + quit_when_idle_received_(false) { |
| +#if !defined(OS_MACOSX) && !defined(OS_ANDROID) |
| + dispatcher_ = NULL; |
| +#endif |
| +} |
| + |
| +#if !defined(OS_MACOSX) && !defined(OS_ANDROID) |
| +MessageLoop::RunLoop::RunLoop(Dispatcher* dispatcher) |
| + : loop_(MessageLoop::current()), |
| + run_called_(false), |
| + stop_called_(false), |
| + running_(false), |
| + run_depth_(0), |
| + quit_when_idle_received_(false), |
| + dispatcher_(dispatcher) { |
| +} |
| +#endif |
| + |
| +MessageLoop::RunLoop::~RunLoop() { |
| +} |
| + |
| +void MessageLoop::RunLoop::Run() { |
| + DCHECK(!run_called_); |
| + run_called_ = true; |
| + |
| + // Allow Stop to be called before Run (why not?). |
| + if (stop_called_) |
| + return; |
| + |
| + // Push RunLoop stack: |
| + base::WeakPtr<RunLoop> previous_run_loop = loop_->run_loop_; |
| + run_depth_ = previous_run_loop? previous_run_loop->run_depth_ + 1 : 1; |
| + loop_->run_loop_ = AsWeakPtr(); |
| + |
| + running_ = true; |
| + loop_->RunHandler(); |
| + running_ = false; |
| + |
| + // Pop RunLoop stack: |
| + loop_->run_loop_ = previous_run_loop; |
| + |
| + // Execute deferred QuitNow, if any: |
| + if (previous_run_loop && previous_run_loop->stop_called_) |
| + loop_->QuitNow(); |
| +} |
| + |
| +void MessageLoop::RunLoop::RunUntilIdle() { |
| + quit_when_idle_received_ = true; |
| + Run(); |
| +} |
| + |
| +void MessageLoop::RunLoop::Stop() { |
| + stop_called_ = true; |
| + if (running_ && loop_->run_loop_ == this) { |
| + // This is the inner-most RunLoop, so quit now. |
| + loop_->QuitNow(); |
| + } |
| +} |
| + |
| +base::Closure MessageLoop::RunLoop::StopClosure() { |
| + return base::Bind(&RunLoop::Stop, AsWeakPtr()); |
| +} |
| + |
| void MessageLoop::Run() { |
| - AutoRunState save_state(this); |
| - RunHandler(); |
| + RunLoop run_loop; |
| + run_loop.Run(); |
| } |
| void MessageLoop::RunAllPending() { |
| - AutoRunState save_state(this); |
| - state_->quit_received = true; // Means run until we would otherwise block. |
| - RunHandler(); |
| + RunLoop run_loop; |
| + run_loop.RunUntilIdle(); |
| } |
| -void MessageLoop::Quit() { |
| +void MessageLoop::QuitWhenIdle() { |
| DCHECK_EQ(this, current()); |
| - if (state_) { |
| - state_->quit_received = true; |
| + if (run_loop_) { |
| + run_loop_->quit_when_idle_received_ = true; |
| } else { |
| NOTREACHED() << "Must be inside Run to call Quit"; |
| } |
| @@ -314,20 +381,20 @@ void MessageLoop::Quit() { |
| void MessageLoop::QuitNow() { |
| DCHECK_EQ(this, current()); |
| - if (state_) { |
| + if (run_loop_) { |
| pump_->Quit(); |
| } else { |
| NOTREACHED() << "Must be inside Run to call Quit"; |
| } |
| } |
| -static void QuitCurrent() { |
| - MessageLoop::current()->Quit(); |
| +static void QuitCurrentWhenIdle() { |
| + MessageLoop::current()->QuitWhenIdle(); |
| } |
| // static |
| -base::Closure MessageLoop::QuitClosure() { |
| - return base::Bind(&QuitCurrent); |
| +base::Closure MessageLoop::QuitWhenIdleClosure() { |
| + return base::Bind(&QuitCurrentWhenIdle); |
| } |
| void MessageLoop::SetNestableTasksAllowed(bool allowed) { |
| @@ -345,7 +412,7 @@ bool MessageLoop::NestableTasksAllowed() const { |
| } |
| bool MessageLoop::IsNested() { |
| - return state_->run_depth > 1; |
| + return run_loop_->run_depth_ > 1; |
| } |
| void MessageLoop::AddTaskObserver(TaskObserver* task_observer) { |
| @@ -366,7 +433,7 @@ void MessageLoop::AssertIdle() const { |
| bool MessageLoop::is_running() const { |
| DCHECK_EQ(this, current()); |
| - return state_ != NULL; |
| + return !!run_loop_; |
| } |
| //------------------------------------------------------------------------------ |
| @@ -404,9 +471,9 @@ void MessageLoop::RunInternal() { |
| StartHistogrammer(); |
| #if !defined(OS_MACOSX) && !defined(OS_ANDROID) |
| - if (state_->dispatcher && type() == TYPE_UI) { |
| + if (run_loop_->dispatcher_ && type() == TYPE_UI) { |
| static_cast<base::MessagePumpForUI*>(pump_.get())-> |
| - RunWithDispatcher(this, state_->dispatcher); |
| + RunWithDispatcher(this, run_loop_->dispatcher_); |
| return; |
| } |
| #endif |
| @@ -415,10 +482,10 @@ void MessageLoop::RunInternal() { |
| } |
| bool MessageLoop::ProcessNextDelayedNonNestableTask() { |
| - if (state_->run_depth != 1) |
| + if (deferred_non_nestable_work_queue_.empty()) |
| return false; |
| - if (deferred_non_nestable_work_queue_.empty()) |
| + if (run_loop_->run_depth_ != 1) |
|
jbates
2012/06/22 02:12:51
Moved this down here, because it's cheaper to chec
|
| return false; |
| PendingTask pending_task = deferred_non_nestable_work_queue_.front(); |
| @@ -463,7 +530,7 @@ void MessageLoop::RunTask(const PendingTask& pending_task) { |
| } |
| bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { |
| - if (pending_task.nestable || state_->run_depth == 1) { |
| + if (pending_task.nestable || run_loop_->run_depth_ == 1) { |
| RunTask(pending_task); |
| // Show that we ran a task (Note: a new one might arrive as a |
| // consequence!). |
| @@ -685,7 +752,7 @@ bool MessageLoop::DoIdleWork() { |
| if (ProcessNextDelayedNonNestableTask()) |
| return true; |
| - if (state_->quit_received) |
| + if (run_loop_->quit_when_idle_received_) |
| pump_->Quit(); |
| return false; |
| @@ -705,30 +772,6 @@ void MessageLoop::ReleaseSoonInternal( |
| } |
| //------------------------------------------------------------------------------ |
| -// MessageLoop::AutoRunState |
| - |
| -MessageLoop::AutoRunState::AutoRunState(MessageLoop* loop) : loop_(loop) { |
| - // Make the loop reference us. |
| - previous_state_ = loop_->state_; |
| - if (previous_state_) { |
| - run_depth = previous_state_->run_depth + 1; |
| - } else { |
| - run_depth = 1; |
| - } |
| - loop_->state_ = this; |
| - |
| - // Initialize the other fields: |
| - quit_received = false; |
| -#if !defined(OS_MACOSX) && !defined(OS_ANDROID) |
| - dispatcher = NULL; |
| -#endif |
| -} |
| - |
| -MessageLoop::AutoRunState::~AutoRunState() { |
| - loop_->state_ = previous_state_; |
| -} |
| - |
| -//------------------------------------------------------------------------------ |
| // MessageLoopForUI |
| #if defined(OS_WIN) |
| @@ -754,16 +797,13 @@ void MessageLoopForUI::RemoveObserver(Observer* observer) { |
| } |
| void MessageLoopForUI::RunWithDispatcher(Dispatcher* dispatcher) { |
| - AutoRunState save_state(this); |
| - state_->dispatcher = dispatcher; |
| - RunHandler(); |
| + RunLoop run_loop(dispatcher); |
| + run_loop.Run(); |
| } |
| void MessageLoopForUI::RunAllPendingWithDispatcher(Dispatcher* dispatcher) { |
| - AutoRunState save_state(this); |
| - state_->dispatcher = dispatcher; |
| - state_->quit_received = true; // Means run until we would otherwise block. |
| - RunHandler(); |
| + RunLoop run_loop(dispatcher); |
| + run_loop.RunUntilIdle(); |
| } |
| #endif // !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID) |