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

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: fetch/merge, no change 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
« no previous file with comments | « base/message_loop.h ('k') | base/message_loop_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 DCHECK(!run_called_);
323 run_called_ = true;
324
325 // Allow Stop to be called before Run (why not?).
326 if (stop_called_)
327 return;
328
329 // Push RunLoop stack:
330 base::WeakPtr<RunLoop> previous_run_loop = loop_->run_loop_;
331 run_depth_ = previous_run_loop? previous_run_loop->run_depth_ + 1 : 1;
332 loop_->run_loop_ = AsWeakPtr();
333
334 running_ = true;
335 loop_->RunHandler();
336 running_ = false;
337
338 // Pop RunLoop stack:
339 loop_->run_loop_ = previous_run_loop;
340
341 // Execute deferred QuitNow, if any:
342 if (previous_run_loop && previous_run_loop->stop_called_)
343 loop_->QuitNow();
344 }
345
346 void MessageLoop::RunLoop::RunUntilIdle() {
347 quit_when_idle_received_ = true;
348 Run();
349 }
350
351 void MessageLoop::RunLoop::Stop() {
352 stop_called_ = true;
353 if (running_ && loop_->run_loop_ == this) {
354 // This is the inner-most RunLoop, so quit now.
355 loop_->QuitNow();
356 }
357 }
358
359 base::Closure MessageLoop::RunLoop::StopClosure() {
360 return base::Bind(&RunLoop::Stop, AsWeakPtr());
361 }
362
295 void MessageLoop::Run() { 363 void MessageLoop::Run() {
296 AutoRunState save_state(this); 364 RunLoop run_loop;
297 RunHandler(); 365 run_loop.Run();
298 } 366 }
299 367
300 void MessageLoop::RunAllPending() { 368 void MessageLoop::RunAllPending() {
301 AutoRunState save_state(this); 369 RunLoop run_loop;
302 state_->quit_received = true; // Means run until we would otherwise block. 370 run_loop.RunUntilIdle();
303 RunHandler();
304 } 371 }
305 372
306 void MessageLoop::Quit() { 373 void MessageLoop::QuitWhenIdle() {
307 DCHECK_EQ(this, current()); 374 DCHECK_EQ(this, current());
308 if (state_) { 375 if (run_loop_) {
309 state_->quit_received = true; 376 run_loop_->quit_when_idle_received_ = true;
310 } else { 377 } else {
311 NOTREACHED() << "Must be inside Run to call Quit"; 378 NOTREACHED() << "Must be inside Run to call Quit";
312 } 379 }
313 } 380 }
314 381
315 void MessageLoop::QuitNow() { 382 void MessageLoop::QuitNow() {
316 DCHECK_EQ(this, current()); 383 DCHECK_EQ(this, current());
317 if (state_) { 384 if (run_loop_) {
318 pump_->Quit(); 385 pump_->Quit();
319 } else { 386 } else {
320 NOTREACHED() << "Must be inside Run to call Quit"; 387 NOTREACHED() << "Must be inside Run to call Quit";
321 } 388 }
322 } 389 }
323 390
324 static void QuitCurrent() { 391 static void QuitCurrentWhenIdle() {
325 MessageLoop::current()->Quit(); 392 MessageLoop::current()->QuitWhenIdle();
326 } 393 }
327 394
328 // static 395 // static
329 base::Closure MessageLoop::QuitClosure() { 396 base::Closure MessageLoop::QuitWhenIdleClosure() {
330 return base::Bind(&QuitCurrent); 397 return base::Bind(&QuitCurrentWhenIdle);
331 } 398 }
332 399
333 void MessageLoop::SetNestableTasksAllowed(bool allowed) { 400 void MessageLoop::SetNestableTasksAllowed(bool allowed) {
334 if (nestable_tasks_allowed_ != allowed) { 401 if (nestable_tasks_allowed_ != allowed) {
335 nestable_tasks_allowed_ = allowed; 402 nestable_tasks_allowed_ = allowed;
336 if (!nestable_tasks_allowed_) 403 if (!nestable_tasks_allowed_)
337 return; 404 return;
338 // Start the native pump if we are not already pumping. 405 // Start the native pump if we are not already pumping.
339 pump_->ScheduleWork(); 406 pump_->ScheduleWork();
340 } 407 }
341 } 408 }
342 409
343 bool MessageLoop::NestableTasksAllowed() const { 410 bool MessageLoop::NestableTasksAllowed() const {
344 return nestable_tasks_allowed_; 411 return nestable_tasks_allowed_;
345 } 412 }
346 413
347 bool MessageLoop::IsNested() { 414 bool MessageLoop::IsNested() {
348 return state_->run_depth > 1; 415 return run_loop_->run_depth_ > 1;
349 } 416 }
350 417
351 void MessageLoop::AddTaskObserver(TaskObserver* task_observer) { 418 void MessageLoop::AddTaskObserver(TaskObserver* task_observer) {
352 DCHECK_EQ(this, current()); 419 DCHECK_EQ(this, current());
353 task_observers_.AddObserver(task_observer); 420 task_observers_.AddObserver(task_observer);
354 } 421 }
355 422
356 void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) { 423 void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) {
357 DCHECK_EQ(this, current()); 424 DCHECK_EQ(this, current());
358 task_observers_.RemoveObserver(task_observer); 425 task_observers_.RemoveObserver(task_observer);
359 } 426 }
360 427
361 void MessageLoop::AssertIdle() const { 428 void MessageLoop::AssertIdle() const {
362 // We only check |incoming_queue_|, since we don't want to lock |work_queue_|. 429 // We only check |incoming_queue_|, since we don't want to lock |work_queue_|.
363 base::AutoLock lock(incoming_queue_lock_); 430 base::AutoLock lock(incoming_queue_lock_);
364 DCHECK(incoming_queue_.empty()); 431 DCHECK(incoming_queue_.empty());
365 } 432 }
366 433
367 bool MessageLoop::is_running() const { 434 bool MessageLoop::is_running() const {
368 DCHECK_EQ(this, current()); 435 DCHECK_EQ(this, current());
369 return state_ != NULL; 436 return !!run_loop_;
370 } 437 }
371 438
372 //------------------------------------------------------------------------------ 439 //------------------------------------------------------------------------------
373 440
374 // Runs the loop in two different SEH modes: 441 // Runs the loop in two different SEH modes:
375 // enable_SEH_restoration_ = false : any unhandled exception goes to the last 442 // enable_SEH_restoration_ = false : any unhandled exception goes to the last
376 // one that calls SetUnhandledExceptionFilter(). 443 // one that calls SetUnhandledExceptionFilter().
377 // enable_SEH_restoration_ = true : any unhandled exception goes to the filter 444 // enable_SEH_restoration_ = true : any unhandled exception goes to the filter
378 // that was existed before the loop was run. 445 // that was existed before the loop was run.
379 void MessageLoop::RunHandler() { 446 void MessageLoop::RunHandler() {
(...skipping 17 matching lines...) Expand all
397 return; 464 return;
398 } 465 }
399 #endif 466 #endif
400 467
401 void MessageLoop::RunInternal() { 468 void MessageLoop::RunInternal() {
402 DCHECK_EQ(this, current()); 469 DCHECK_EQ(this, current());
403 470
404 StartHistogrammer(); 471 StartHistogrammer();
405 472
406 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) 473 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
407 if (state_->dispatcher && type() == TYPE_UI) { 474 if (run_loop_->dispatcher_ && type() == TYPE_UI) {
408 static_cast<base::MessagePumpForUI*>(pump_.get())-> 475 static_cast<base::MessagePumpForUI*>(pump_.get())->
409 RunWithDispatcher(this, state_->dispatcher); 476 RunWithDispatcher(this, run_loop_->dispatcher_);
410 return; 477 return;
411 } 478 }
412 #endif 479 #endif
413 480
414 pump_->Run(this); 481 pump_->Run(this);
415 } 482 }
416 483
417 bool MessageLoop::ProcessNextDelayedNonNestableTask() { 484 bool MessageLoop::ProcessNextDelayedNonNestableTask() {
418 if (state_->run_depth != 1)
419 return false;
420
421 if (deferred_non_nestable_work_queue_.empty()) 485 if (deferred_non_nestable_work_queue_.empty())
422 return false; 486 return false;
423 487
488 if (run_loop_->run_depth_ != 1)
jbates 2012/06/22 02:12:51 Moved this down here, because it's cheaper to chec
489 return false;
490
424 PendingTask pending_task = deferred_non_nestable_work_queue_.front(); 491 PendingTask pending_task = deferred_non_nestable_work_queue_.front();
425 deferred_non_nestable_work_queue_.pop(); 492 deferred_non_nestable_work_queue_.pop();
426 493
427 RunTask(pending_task); 494 RunTask(pending_task);
428 return true; 495 return true;
429 } 496 }
430 497
431 void MessageLoop::RunTask(const PendingTask& pending_task) { 498 void MessageLoop::RunTask(const PendingTask& pending_task) {
432 TRACE_EVENT2("task", "MessageLoop::RunTask", 499 TRACE_EVENT2("task", "MessageLoop::RunTask",
433 "src_file", pending_task.posted_from.file_name(), 500 "src_file", pending_task.posted_from.file_name(),
(...skipping 22 matching lines...) Expand all
456 FOR_EACH_OBSERVER(TaskObserver, task_observers_, 523 FOR_EACH_OBSERVER(TaskObserver, task_observers_,
457 DidProcessTask(pending_task.time_posted)); 524 DidProcessTask(pending_task.time_posted));
458 525
459 tracked_objects::ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, 526 tracked_objects::ThreadData::TallyRunOnNamedThreadIfTracking(pending_task,
460 start_time, tracked_objects::ThreadData::NowForEndOfRun()); 527 start_time, tracked_objects::ThreadData::NowForEndOfRun());
461 528
462 nestable_tasks_allowed_ = true; 529 nestable_tasks_allowed_ = true;
463 } 530 }
464 531
465 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { 532 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) {
466 if (pending_task.nestable || state_->run_depth == 1) { 533 if (pending_task.nestable || run_loop_->run_depth_ == 1) {
467 RunTask(pending_task); 534 RunTask(pending_task);
468 // Show that we ran a task (Note: a new one might arrive as a 535 // Show that we ran a task (Note: a new one might arrive as a
469 // consequence!). 536 // consequence!).
470 return true; 537 return true;
471 } 538 }
472 539
473 // We couldn't run the task now because we're in a nested message loop 540 // We couldn't run the task now because we're in a nested message loop
474 // and the task isn't nestable. 541 // and the task isn't nestable.
475 deferred_non_nestable_work_queue_.push(pending_task); 542 deferred_non_nestable_work_queue_.push(pending_task);
476 return false; 543 return false;
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 if (!delayed_work_queue_.empty()) 745 if (!delayed_work_queue_.empty())
679 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time; 746 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
680 747
681 return DeferOrRunPendingTask(pending_task); 748 return DeferOrRunPendingTask(pending_task);
682 } 749 }
683 750
684 bool MessageLoop::DoIdleWork() { 751 bool MessageLoop::DoIdleWork() {
685 if (ProcessNextDelayedNonNestableTask()) 752 if (ProcessNextDelayedNonNestableTask())
686 return true; 753 return true;
687 754
688 if (state_->quit_received) 755 if (run_loop_->quit_when_idle_received_)
689 pump_->Quit(); 756 pump_->Quit();
690 757
691 return false; 758 return false;
692 } 759 }
693 760
694 void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here, 761 void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here,
695 void(*deleter)(const void*), 762 void(*deleter)(const void*),
696 const void* object) { 763 const void* object) {
697 PostNonNestableTask(from_here, base::Bind(deleter, object)); 764 PostNonNestableTask(from_here, base::Bind(deleter, object));
698 } 765 }
699 766
700 void MessageLoop::ReleaseSoonInternal( 767 void MessageLoop::ReleaseSoonInternal(
701 const tracked_objects::Location& from_here, 768 const tracked_objects::Location& from_here,
702 void(*releaser)(const void*), 769 void(*releaser)(const void*),
703 const void* object) { 770 const void* object) {
704 PostNonNestableTask(from_here, base::Bind(releaser, object)); 771 PostNonNestableTask(from_here, base::Bind(releaser, object));
705 } 772 }
706 773
707 //------------------------------------------------------------------------------ 774 //------------------------------------------------------------------------------
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 775 // MessageLoopForUI
733 776
734 #if defined(OS_WIN) 777 #if defined(OS_WIN)
735 void MessageLoopForUI::DidProcessMessage(const MSG& message) { 778 void MessageLoopForUI::DidProcessMessage(const MSG& message) {
736 pump_win()->DidProcessMessage(message); 779 pump_win()->DidProcessMessage(message);
737 } 780 }
738 #endif // defined(OS_WIN) 781 #endif // defined(OS_WIN)
739 782
740 #if defined(OS_ANDROID) 783 #if defined(OS_ANDROID)
741 void MessageLoopForUI::Start() { 784 void MessageLoopForUI::Start() {
742 // No Histogram support for UI message loop as it is managed by Java side 785 // No Histogram support for UI message loop as it is managed by Java side
743 static_cast<base::MessagePumpForUI*>(pump_.get())->Start(this); 786 static_cast<base::MessagePumpForUI*>(pump_.get())->Start(this);
744 } 787 }
745 #endif 788 #endif
746 789
747 #if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID) 790 #if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID)
748 void MessageLoopForUI::AddObserver(Observer* observer) { 791 void MessageLoopForUI::AddObserver(Observer* observer) {
749 pump_ui()->AddObserver(observer); 792 pump_ui()->AddObserver(observer);
750 } 793 }
751 794
752 void MessageLoopForUI::RemoveObserver(Observer* observer) { 795 void MessageLoopForUI::RemoveObserver(Observer* observer) {
753 pump_ui()->RemoveObserver(observer); 796 pump_ui()->RemoveObserver(observer);
754 } 797 }
755 798
756 void MessageLoopForUI::RunWithDispatcher(Dispatcher* dispatcher) { 799 void MessageLoopForUI::RunWithDispatcher(Dispatcher* dispatcher) {
757 AutoRunState save_state(this); 800 RunLoop run_loop(dispatcher);
758 state_->dispatcher = dispatcher; 801 run_loop.Run();
759 RunHandler();
760 } 802 }
761 803
762 void MessageLoopForUI::RunAllPendingWithDispatcher(Dispatcher* dispatcher) { 804 void MessageLoopForUI::RunAllPendingWithDispatcher(Dispatcher* dispatcher) {
763 AutoRunState save_state(this); 805 RunLoop run_loop(dispatcher);
764 state_->dispatcher = dispatcher; 806 run_loop.RunUntilIdle();
765 state_->quit_received = true; // Means run until we would otherwise block.
766 RunHandler();
767 } 807 }
768 808
769 #endif // !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID) 809 #endif // !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID)
770 810
771 //------------------------------------------------------------------------------ 811 //------------------------------------------------------------------------------
772 // MessageLoopForIO 812 // MessageLoopForIO
773 813
774 #if defined(OS_WIN) 814 #if defined(OS_WIN)
775 815
776 void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) { 816 void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) {
(...skipping 13 matching lines...) Expand all
790 Watcher *delegate) { 830 Watcher *delegate) {
791 return pump_libevent()->WatchFileDescriptor( 831 return pump_libevent()->WatchFileDescriptor(
792 fd, 832 fd,
793 persistent, 833 persistent,
794 static_cast<base::MessagePumpLibevent::Mode>(mode), 834 static_cast<base::MessagePumpLibevent::Mode>(mode),
795 controller, 835 controller,
796 delegate); 836 delegate);
797 } 837 }
798 838
799 #endif 839 #endif
OLDNEW
« no previous file with comments | « 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