Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(803)

Side by Side Diff: base/message_loop.cc

Issue 10479018: Add base::RunLoop and update ui_test_utils to use it to reduce flakiness (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: android compile Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 MessageLoop::DestructionObserver::~DestructionObserver() { 124 MessageLoop::DestructionObserver::~DestructionObserver() {
125 } 125 }
126 126
127 //------------------------------------------------------------------------------ 127 //------------------------------------------------------------------------------
128 128
129 MessageLoop::MessageLoop(Type type) 129 MessageLoop::MessageLoop(Type type)
130 : type_(type), 130 : type_(type),
131 nestable_tasks_allowed_(true), 131 nestable_tasks_allowed_(true),
132 exception_restoration_(false), 132 exception_restoration_(false),
133 message_histogram_(NULL), 133 message_histogram_(NULL),
134 state_(NULL),
135 #ifdef OS_WIN 134 #ifdef OS_WIN
136 os_modal_loop_(false), 135 os_modal_loop_(false),
137 #endif // OS_WIN 136 #endif // OS_WIN
138 next_sequence_num_(0) { 137 next_sequence_num_(0) {
139 DCHECK(!current()) << "should only have one message loop per thread"; 138 DCHECK(!current()) << "should only have one message loop per thread";
140 lazy_tls_ptr.Pointer()->Set(this); 139 lazy_tls_ptr.Pointer()->Set(this);
141 140
142 message_loop_proxy_ = new base::MessageLoopProxyImpl(); 141 message_loop_proxy_ = new base::MessageLoopProxyImpl();
143 thread_task_runner_handle_.reset( 142 thread_task_runner_handle_.reset(
144 new base::ThreadTaskRunnerHandle(message_loop_proxy_)); 143 new base::ThreadTaskRunnerHandle(message_loop_proxy_));
(...skipping 28 matching lines...) Expand all
173 pump_ = MESSAGE_PUMP_IO; 172 pump_ = MESSAGE_PUMP_IO;
174 } else { 173 } else {
175 DCHECK_EQ(TYPE_DEFAULT, type_); 174 DCHECK_EQ(TYPE_DEFAULT, type_);
176 pump_ = new base::MessagePumpDefault(); 175 pump_ = new base::MessagePumpDefault();
177 } 176 }
178 } 177 }
179 178
180 MessageLoop::~MessageLoop() { 179 MessageLoop::~MessageLoop() {
181 DCHECK_EQ(this, current()); 180 DCHECK_EQ(this, current());
182 181
183 DCHECK(!state_); 182 DCHECK(!run_loop_);
184 183
185 // Clean up any unprocessed tasks, but take care: deleting a task could 184 // Clean up any unprocessed tasks, but take care: deleting a task could
186 // result in the addition of more tasks (e.g., via DeleteSoon). We set a 185 // result in the addition of more tasks (e.g., via DeleteSoon). We set a
187 // limit on the number of times we will allow a deleted task to generate more 186 // limit on the number of times we will allow a deleted task to generate more
188 // tasks. Normally, we should only pass through this loop once or twice. If 187 // tasks. Normally, we should only pass through this loop once or twice. If
189 // we end up hitting the loop limit, then it is probably due to one task that 188 // we end up hitting the loop limit, then it is probably due to one task that
190 // is being stubborn. Inspect the queues to see who is left. 189 // is being stubborn. Inspect the queues to see who is left.
191 bool did_work; 190 bool did_work;
192 for (int i = 0; i < 100; ++i) { 191 for (int i = 0; i < 100; ++i) {
193 DeletePendingTasks(); 192 DeletePendingTasks();
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 void MessageLoop::PostNonNestableDelayedTask( 284 void MessageLoop::PostNonNestableDelayedTask(
286 const tracked_objects::Location& from_here, 285 const tracked_objects::Location& from_here,
287 const base::Closure& task, 286 const base::Closure& task,
288 TimeDelta delay) { 287 TimeDelta delay) {
289 DCHECK(!task.is_null()) << from_here.ToString(); 288 DCHECK(!task.is_null()) << from_here.ToString();
290 PendingTask pending_task( 289 PendingTask pending_task(
291 from_here, task, CalculateDelayedRuntime(delay), false); 290 from_here, task, CalculateDelayedRuntime(delay), false);
292 AddToIncomingQueue(&pending_task); 291 AddToIncomingQueue(&pending_task);
293 } 292 }
294 293
294 MessageLoop::RunLoop::RunLoop()
295 : loop_(MessageLoop::current()),
296 run_called_(false),
297 stop_called_(false),
298 running_(false),
299 run_depth_(0),
300 quit_when_idle_received_(false) {
301 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
302 dispatcher_ = NULL;
303 #endif
304 }
305
306 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
307 MessageLoop::RunLoop::RunLoop(Dispatcher* dispatcher)
308 : loop_(MessageLoop::current()),
309 run_called_(false),
310 stop_called_(false),
311 running_(false),
312 run_depth_(0),
313 quit_when_idle_received_(false),
314 dispatcher_(dispatcher) {
315 }
316 #endif
317
318 MessageLoop::RunLoop::~RunLoop() {
319 }
320
321 void MessageLoop::RunLoop::Run() {
322 if (!BeforeRun())
323 return;
324 loop_->RunHandler();
325 AfterRun();
326 }
327
328 void MessageLoop::RunLoop::RunUntilIdle() {
329 quit_when_idle_received_ = true;
330 Run();
331 }
332
333 void MessageLoop::RunLoop::Stop() {
334 stop_called_ = true;
335 if (running_ && loop_->run_loop_ == this) {
336 // This is the inner-most RunLoop, so quit now.
337 loop_->QuitNow();
338 }
339 }
340
341 base::Closure MessageLoop::RunLoop::StopClosure() {
342 return base::Bind(&RunLoop::Stop, AsWeakPtr());
343 }
344
345 bool MessageLoop::RunLoop::BeforeRun() {
346 DCHECK(!run_called_);
347 run_called_ = true;
348
349 // Allow Stop to be called before Run.
350 if (stop_called_)
351 return false;
352
353 // Push RunLoop stack:
354 previous_run_loop_ = loop_->run_loop_;
355 run_depth_ = previous_run_loop_? previous_run_loop_->run_depth_ + 1 : 1;
356 loop_->run_loop_ = AsWeakPtr();
357
358 running_ = true;
359 return true;
360 }
361
362 void MessageLoop::RunLoop::AfterRun() {
363 running_ = false;
364
365 // Pop RunLoop stack:
366 loop_->run_loop_ = previous_run_loop_;
367
368 // Execute deferred QuitNow, if any:
369 if (previous_run_loop_ && previous_run_loop_->stop_called_)
370 loop_->QuitNow();
371 }
372
295 void MessageLoop::Run() { 373 void MessageLoop::Run() {
296 AutoRunState save_state(this); 374 RunLoop run_loop;
297 RunHandler(); 375 run_loop.Run();
298 } 376 }
299 377
300 void MessageLoop::RunAllPending() { 378 void MessageLoop::RunAllPending() {
301 AutoRunState save_state(this); 379 RunLoop run_loop;
302 state_->quit_received = true; // Means run until we would otherwise block. 380 run_loop.RunUntilIdle();
303 RunHandler();
304 } 381 }
305 382
306 void MessageLoop::Quit() { 383 void MessageLoop::QuitWhenIdle() {
307 DCHECK_EQ(this, current()); 384 DCHECK_EQ(this, current());
308 if (state_) { 385 if (run_loop_) {
309 state_->quit_received = true; 386 run_loop_->quit_when_idle_received_ = true;
310 } else { 387 } else {
311 NOTREACHED() << "Must be inside Run to call Quit"; 388 NOTREACHED() << "Must be inside Run to call Quit";
312 } 389 }
313 } 390 }
314 391
315 void MessageLoop::QuitNow() { 392 void MessageLoop::QuitNow() {
316 DCHECK_EQ(this, current()); 393 DCHECK_EQ(this, current());
317 if (state_) { 394 if (run_loop_) {
318 pump_->Quit(); 395 pump_->Quit();
319 } else { 396 } else {
320 NOTREACHED() << "Must be inside Run to call Quit"; 397 NOTREACHED() << "Must be inside Run to call Quit";
321 } 398 }
322 } 399 }
323 400
324 static void QuitCurrent() { 401 static void QuitCurrentWhenIdle() {
325 MessageLoop::current()->Quit(); 402 MessageLoop::current()->QuitWhenIdle();
326 } 403 }
327 404
328 // static 405 // static
329 base::Closure MessageLoop::QuitClosure() { 406 base::Closure MessageLoop::QuitWhenIdleClosure() {
330 return base::Bind(&QuitCurrent); 407 return base::Bind(&QuitCurrentWhenIdle);
331 } 408 }
332 409
333 void MessageLoop::SetNestableTasksAllowed(bool allowed) { 410 void MessageLoop::SetNestableTasksAllowed(bool allowed) {
334 if (nestable_tasks_allowed_ != allowed) { 411 if (nestable_tasks_allowed_ != allowed) {
335 nestable_tasks_allowed_ = allowed; 412 nestable_tasks_allowed_ = allowed;
336 if (!nestable_tasks_allowed_) 413 if (!nestable_tasks_allowed_)
337 return; 414 return;
338 // Start the native pump if we are not already pumping. 415 // Start the native pump if we are not already pumping.
339 pump_->ScheduleWork(); 416 pump_->ScheduleWork();
340 } 417 }
341 } 418 }
342 419
343 bool MessageLoop::NestableTasksAllowed() const { 420 bool MessageLoop::NestableTasksAllowed() const {
344 return nestable_tasks_allowed_; 421 return nestable_tasks_allowed_;
345 } 422 }
346 423
347 bool MessageLoop::IsNested() { 424 bool MessageLoop::IsNested() {
348 return state_->run_depth > 1; 425 return run_loop_->run_depth_ > 1;
349 } 426 }
350 427
351 void MessageLoop::AddTaskObserver(TaskObserver* task_observer) { 428 void MessageLoop::AddTaskObserver(TaskObserver* task_observer) {
352 DCHECK_EQ(this, current()); 429 DCHECK_EQ(this, current());
353 task_observers_.AddObserver(task_observer); 430 task_observers_.AddObserver(task_observer);
354 } 431 }
355 432
356 void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) { 433 void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) {
357 DCHECK_EQ(this, current()); 434 DCHECK_EQ(this, current());
358 task_observers_.RemoveObserver(task_observer); 435 task_observers_.RemoveObserver(task_observer);
359 } 436 }
360 437
361 void MessageLoop::AssertIdle() const { 438 void MessageLoop::AssertIdle() const {
362 // We only check |incoming_queue_|, since we don't want to lock |work_queue_|. 439 // We only check |incoming_queue_|, since we don't want to lock |work_queue_|.
363 base::AutoLock lock(incoming_queue_lock_); 440 base::AutoLock lock(incoming_queue_lock_);
364 DCHECK(incoming_queue_.empty()); 441 DCHECK(incoming_queue_.empty());
365 } 442 }
366 443
367 bool MessageLoop::is_running() const { 444 bool MessageLoop::is_running() const {
368 DCHECK_EQ(this, current()); 445 DCHECK_EQ(this, current());
369 return state_ != NULL; 446 return !!run_loop_;
370 } 447 }
371 448
372 //------------------------------------------------------------------------------ 449 //------------------------------------------------------------------------------
373 450
374 // Runs the loop in two different SEH modes: 451 // Runs the loop in two different SEH modes:
375 // enable_SEH_restoration_ = false : any unhandled exception goes to the last 452 // enable_SEH_restoration_ = false : any unhandled exception goes to the last
376 // one that calls SetUnhandledExceptionFilter(). 453 // one that calls SetUnhandledExceptionFilter().
377 // enable_SEH_restoration_ = true : any unhandled exception goes to the filter 454 // enable_SEH_restoration_ = true : any unhandled exception goes to the filter
378 // that was existed before the loop was run. 455 // that was existed before the loop was run.
379 void MessageLoop::RunHandler() { 456 void MessageLoop::RunHandler() {
(...skipping 17 matching lines...) Expand all
397 return; 474 return;
398 } 475 }
399 #endif 476 #endif
400 477
401 void MessageLoop::RunInternal() { 478 void MessageLoop::RunInternal() {
402 DCHECK_EQ(this, current()); 479 DCHECK_EQ(this, current());
403 480
404 StartHistogrammer(); 481 StartHistogrammer();
405 482
406 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) 483 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
407 if (state_->dispatcher && type() == TYPE_UI) { 484 if (run_loop_->dispatcher_ && type() == TYPE_UI) {
408 static_cast<base::MessagePumpForUI*>(pump_.get())-> 485 static_cast<base::MessagePumpForUI*>(pump_.get())->
409 RunWithDispatcher(this, state_->dispatcher); 486 RunWithDispatcher(this, run_loop_->dispatcher_);
410 return; 487 return;
411 } 488 }
412 #endif 489 #endif
413 490
414 pump_->Run(this); 491 pump_->Run(this);
415 } 492 }
416 493
417 bool MessageLoop::ProcessNextDelayedNonNestableTask() { 494 bool MessageLoop::ProcessNextDelayedNonNestableTask() {
418 if (state_->run_depth != 1)
419 return false;
420
421 if (deferred_non_nestable_work_queue_.empty()) 495 if (deferred_non_nestable_work_queue_.empty())
422 return false; 496 return false;
423 497
498 if (run_loop_->run_depth_ != 1)
499 return false;
500
424 PendingTask pending_task = deferred_non_nestable_work_queue_.front(); 501 PendingTask pending_task = deferred_non_nestable_work_queue_.front();
425 deferred_non_nestable_work_queue_.pop(); 502 deferred_non_nestable_work_queue_.pop();
426 503
427 RunTask(pending_task); 504 RunTask(pending_task);
428 return true; 505 return true;
429 } 506 }
430 507
431 void MessageLoop::RunTask(const PendingTask& pending_task) { 508 void MessageLoop::RunTask(const PendingTask& pending_task) {
432 TRACE_EVENT2("task", "MessageLoop::RunTask", 509 TRACE_EVENT2("task", "MessageLoop::RunTask",
433 "src_file", pending_task.posted_from.file_name(), 510 "src_file", pending_task.posted_from.file_name(),
(...skipping 22 matching lines...) Expand all
456 FOR_EACH_OBSERVER(TaskObserver, task_observers_, 533 FOR_EACH_OBSERVER(TaskObserver, task_observers_,
457 DidProcessTask(pending_task.time_posted)); 534 DidProcessTask(pending_task.time_posted));
458 535
459 tracked_objects::ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, 536 tracked_objects::ThreadData::TallyRunOnNamedThreadIfTracking(pending_task,
460 start_time, tracked_objects::ThreadData::NowForEndOfRun()); 537 start_time, tracked_objects::ThreadData::NowForEndOfRun());
461 538
462 nestable_tasks_allowed_ = true; 539 nestable_tasks_allowed_ = true;
463 } 540 }
464 541
465 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { 542 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) {
466 if (pending_task.nestable || state_->run_depth == 1) { 543 if (pending_task.nestable || run_loop_->run_depth_ == 1) {
467 RunTask(pending_task); 544 RunTask(pending_task);
468 // Show that we ran a task (Note: a new one might arrive as a 545 // Show that we ran a task (Note: a new one might arrive as a
469 // consequence!). 546 // consequence!).
470 return true; 547 return true;
471 } 548 }
472 549
473 // We couldn't run the task now because we're in a nested message loop 550 // We couldn't run the task now because we're in a nested message loop
474 // and the task isn't nestable. 551 // and the task isn't nestable.
475 deferred_non_nestable_work_queue_.push(pending_task); 552 deferred_non_nestable_work_queue_.push(pending_task);
476 return false; 553 return false;
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 if (!delayed_work_queue_.empty()) 755 if (!delayed_work_queue_.empty())
679 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time; 756 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
680 757
681 return DeferOrRunPendingTask(pending_task); 758 return DeferOrRunPendingTask(pending_task);
682 } 759 }
683 760
684 bool MessageLoop::DoIdleWork() { 761 bool MessageLoop::DoIdleWork() {
685 if (ProcessNextDelayedNonNestableTask()) 762 if (ProcessNextDelayedNonNestableTask())
686 return true; 763 return true;
687 764
688 if (state_->quit_received) 765 if (run_loop_->quit_when_idle_received_)
689 pump_->Quit(); 766 pump_->Quit();
690 767
691 return false; 768 return false;
692 } 769 }
693 770
694 void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here, 771 void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here,
695 void(*deleter)(const void*), 772 void(*deleter)(const void*),
696 const void* object) { 773 const void* object) {
697 PostNonNestableTask(from_here, base::Bind(deleter, object)); 774 PostNonNestableTask(from_here, base::Bind(deleter, object));
698 } 775 }
699 776
700 void MessageLoop::ReleaseSoonInternal( 777 void MessageLoop::ReleaseSoonInternal(
701 const tracked_objects::Location& from_here, 778 const tracked_objects::Location& from_here,
702 void(*releaser)(const void*), 779 void(*releaser)(const void*),
703 const void* object) { 780 const void* object) {
704 PostNonNestableTask(from_here, base::Bind(releaser, object)); 781 PostNonNestableTask(from_here, base::Bind(releaser, object));
705 } 782 }
706 783
707 //------------------------------------------------------------------------------ 784 //------------------------------------------------------------------------------
708 // MessageLoop::AutoRunState
709
710 MessageLoop::AutoRunState::AutoRunState(MessageLoop* loop) : loop_(loop) {
711 // Make the loop reference us.
712 previous_state_ = loop_->state_;
713 if (previous_state_) {
714 run_depth = previous_state_->run_depth + 1;
715 } else {
716 run_depth = 1;
717 }
718 loop_->state_ = this;
719
720 // Initialize the other fields:
721 quit_received = false;
722 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
723 dispatcher = NULL;
724 #endif
725 }
726
727 MessageLoop::AutoRunState::~AutoRunState() {
728 loop_->state_ = previous_state_;
729 }
730
731 //------------------------------------------------------------------------------
732 // MessageLoopForUI 785 // MessageLoopForUI
733 786
734 #if defined(OS_WIN) 787 #if defined(OS_WIN)
735 void MessageLoopForUI::DidProcessMessage(const MSG& message) { 788 void MessageLoopForUI::DidProcessMessage(const MSG& message) {
736 pump_win()->DidProcessMessage(message); 789 pump_win()->DidProcessMessage(message);
737 } 790 }
738 #endif // defined(OS_WIN) 791 #endif // defined(OS_WIN)
739 792
740 #if defined(OS_ANDROID) 793 #if defined(OS_ANDROID)
741 void MessageLoopForUI::Start() { 794 void MessageLoopForUI::Start() {
742 // No Histogram support for UI message loop as it is managed by Java side 795 // No Histogram support for UI message loop as it is managed by Java side
743 static_cast<base::MessagePumpForUI*>(pump_.get())->Start(this); 796 static_cast<base::MessagePumpForUI*>(pump_.get())->Start(this);
744 } 797 }
745 #endif 798 #endif
746 799
747 #if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID) 800 #if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID)
748 void MessageLoopForUI::AddObserver(Observer* observer) { 801 void MessageLoopForUI::AddObserver(Observer* observer) {
749 pump_ui()->AddObserver(observer); 802 pump_ui()->AddObserver(observer);
750 } 803 }
751 804
752 void MessageLoopForUI::RemoveObserver(Observer* observer) { 805 void MessageLoopForUI::RemoveObserver(Observer* observer) {
753 pump_ui()->RemoveObserver(observer); 806 pump_ui()->RemoveObserver(observer);
754 } 807 }
755 808
756 void MessageLoopForUI::RunWithDispatcher(Dispatcher* dispatcher) { 809 void MessageLoopForUI::RunWithDispatcher(Dispatcher* dispatcher) {
757 AutoRunState save_state(this); 810 RunLoop run_loop(dispatcher);
758 state_->dispatcher = dispatcher; 811 run_loop.Run();
759 RunHandler();
760 } 812 }
761 813
762 void MessageLoopForUI::RunAllPendingWithDispatcher(Dispatcher* dispatcher) { 814 void MessageLoopForUI::RunAllPendingWithDispatcher(Dispatcher* dispatcher) {
763 AutoRunState save_state(this); 815 RunLoop run_loop(dispatcher);
764 state_->dispatcher = dispatcher; 816 run_loop.RunUntilIdle();
765 state_->quit_received = true; // Means run until we would otherwise block.
766 RunHandler();
767 } 817 }
768 818
769 #endif // !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID) 819 #endif // !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID)
770 820
771 //------------------------------------------------------------------------------ 821 //------------------------------------------------------------------------------
772 // MessageLoopForIO 822 // MessageLoopForIO
773 823
774 #if defined(OS_WIN) 824 #if defined(OS_WIN)
775 825
776 void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) { 826 void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) {
(...skipping 13 matching lines...) Expand all
790 Watcher *delegate) { 840 Watcher *delegate) {
791 return pump_libevent()->WatchFileDescriptor( 841 return pump_libevent()->WatchFileDescriptor(
792 fd, 842 fd,
793 persistent, 843 persistent,
794 static_cast<base::MessagePumpLibevent::Mode>(mode), 844 static_cast<base::MessagePumpLibevent::Mode>(mode),
795 controller, 845 controller,
796 delegate); 846 delegate);
797 } 847 }
798 848
799 #endif 849 #endif
OLDNEW
« base/message_loop.h ('K') | « base/message_loop.h ('k') | base/message_loop_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698