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

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: phajdan feedback Created 8 years, 5 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"
11 #include "base/debug/alias.h" 11 #include "base/debug/alias.h"
12 #include "base/debug/trace_event.h" 12 #include "base/debug/trace_event.h"
13 #include "base/lazy_instance.h" 13 #include "base/lazy_instance.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
16 #include "base/message_loop_proxy_impl.h" 16 #include "base/message_loop_proxy_impl.h"
17 #include "base/message_pump_default.h" 17 #include "base/message_pump_default.h"
18 #include "base/metrics/histogram.h" 18 #include "base/metrics/histogram.h"
19 #include "base/run_loop.h"
19 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" 20 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
20 #include "base/thread_task_runner_handle.h" 21 #include "base/thread_task_runner_handle.h"
21 #include "base/threading/thread_local.h" 22 #include "base/threading/thread_local.h"
22 #include "base/time.h" 23 #include "base/time.h"
23 #include "base/tracked_objects.h" 24 #include "base/tracked_objects.h"
24 25
25 #if defined(OS_MACOSX) 26 #if defined(OS_MACOSX)
26 #include "base/message_pump_mac.h" 27 #include "base/message_pump_mac.h"
27 #endif 28 #endif
28 #if defined(OS_POSIX) 29 #if defined(OS_POSIX)
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 MessageLoop::DestructionObserver::~DestructionObserver() { 125 MessageLoop::DestructionObserver::~DestructionObserver() {
125 } 126 }
126 127
127 //------------------------------------------------------------------------------ 128 //------------------------------------------------------------------------------
128 129
129 MessageLoop::MessageLoop(Type type) 130 MessageLoop::MessageLoop(Type type)
130 : type_(type), 131 : type_(type),
131 nestable_tasks_allowed_(true), 132 nestable_tasks_allowed_(true),
132 exception_restoration_(false), 133 exception_restoration_(false),
133 message_histogram_(NULL), 134 message_histogram_(NULL),
134 state_(NULL), 135 run_loop_(NULL),
135 #ifdef OS_WIN 136 #ifdef OS_WIN
136 os_modal_loop_(false), 137 os_modal_loop_(false),
137 #endif // OS_WIN 138 #endif // OS_WIN
138 next_sequence_num_(0) { 139 next_sequence_num_(0) {
139 DCHECK(!current()) << "should only have one message loop per thread"; 140 DCHECK(!current()) << "should only have one message loop per thread";
140 lazy_tls_ptr.Pointer()->Set(this); 141 lazy_tls_ptr.Pointer()->Set(this);
141 142
142 message_loop_proxy_ = new base::MessageLoopProxyImpl(); 143 message_loop_proxy_ = new base::MessageLoopProxyImpl();
143 thread_task_runner_handle_.reset( 144 thread_task_runner_handle_.reset(
144 new base::ThreadTaskRunnerHandle(message_loop_proxy_)); 145 new base::ThreadTaskRunnerHandle(message_loop_proxy_));
(...skipping 28 matching lines...) Expand all
173 pump_ = MESSAGE_PUMP_IO; 174 pump_ = MESSAGE_PUMP_IO;
174 } else { 175 } else {
175 DCHECK_EQ(TYPE_DEFAULT, type_); 176 DCHECK_EQ(TYPE_DEFAULT, type_);
176 pump_ = new base::MessagePumpDefault(); 177 pump_ = new base::MessagePumpDefault();
177 } 178 }
178 } 179 }
179 180
180 MessageLoop::~MessageLoop() { 181 MessageLoop::~MessageLoop() {
181 DCHECK_EQ(this, current()); 182 DCHECK_EQ(this, current());
182 183
183 DCHECK(!state_); 184 DCHECK(!run_loop_);
184 185
185 // Clean up any unprocessed tasks, but take care: deleting a task could 186 // 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 187 // 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 188 // 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 189 // 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 190 // 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. 191 // is being stubborn. Inspect the queues to see who is left.
191 bool did_work; 192 bool did_work;
192 for (int i = 0; i < 100; ++i) { 193 for (int i = 0; i < 100; ++i) {
193 DeletePendingTasks(); 194 DeletePendingTasks();
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 const tracked_objects::Location& from_here, 287 const tracked_objects::Location& from_here,
287 const base::Closure& task, 288 const base::Closure& task,
288 TimeDelta delay) { 289 TimeDelta delay) {
289 DCHECK(!task.is_null()) << from_here.ToString(); 290 DCHECK(!task.is_null()) << from_here.ToString();
290 PendingTask pending_task( 291 PendingTask pending_task(
291 from_here, task, CalculateDelayedRuntime(delay), false); 292 from_here, task, CalculateDelayedRuntime(delay), false);
292 AddToIncomingQueue(&pending_task); 293 AddToIncomingQueue(&pending_task);
293 } 294 }
294 295
295 void MessageLoop::Run() { 296 void MessageLoop::Run() {
296 AutoRunState save_state(this); 297 base::RunLoop run_loop;
297 RunHandler(); 298 run_loop.Run();
298 } 299 }
299 300
300 void MessageLoop::RunAllPending() { 301 void MessageLoop::RunUntilIdle() {
301 AutoRunState save_state(this); 302 base::RunLoop run_loop;
302 state_->quit_received = true; // Means run until we would otherwise block. 303 run_loop.RunUntilIdle();
303 RunHandler();
304 } 304 }
305 305
306 void MessageLoop::Quit() { 306 void MessageLoop::QuitWhenIdle() {
307 DCHECK_EQ(this, current()); 307 DCHECK_EQ(this, current());
308 if (state_) { 308 if (run_loop_) {
309 state_->quit_received = true; 309 run_loop_->quit_when_idle_received_ = true;
310 } else { 310 } else {
311 NOTREACHED() << "Must be inside Run to call Quit"; 311 NOTREACHED() << "Must be inside Run to call Quit";
312 } 312 }
313 } 313 }
314 314
315 void MessageLoop::QuitNow() { 315 void MessageLoop::QuitNow() {
316 DCHECK_EQ(this, current()); 316 DCHECK_EQ(this, current());
317 if (state_) { 317 if (run_loop_) {
318 pump_->Quit(); 318 pump_->Quit();
319 } else { 319 } else {
320 NOTREACHED() << "Must be inside Run to call Quit"; 320 NOTREACHED() << "Must be inside Run to call Quit";
321 } 321 }
322 } 322 }
323 323
324 static void QuitCurrent() { 324 static void QuitCurrentWhenIdle() {
325 MessageLoop::current()->Quit(); 325 MessageLoop::current()->QuitWhenIdle();
326 } 326 }
327 327
328 // static 328 // static
329 base::Closure MessageLoop::QuitClosure() { 329 base::Closure MessageLoop::QuitWhenIdleClosure() {
330 return base::Bind(&QuitCurrent); 330 return base::Bind(&QuitCurrentWhenIdle);
331 } 331 }
332 332
333 void MessageLoop::SetNestableTasksAllowed(bool allowed) { 333 void MessageLoop::SetNestableTasksAllowed(bool allowed) {
334 if (nestable_tasks_allowed_ != allowed) { 334 if (nestable_tasks_allowed_ != allowed) {
335 nestable_tasks_allowed_ = allowed; 335 nestable_tasks_allowed_ = allowed;
336 if (!nestable_tasks_allowed_) 336 if (!nestable_tasks_allowed_)
337 return; 337 return;
338 // Start the native pump if we are not already pumping. 338 // Start the native pump if we are not already pumping.
339 pump_->ScheduleWork(); 339 pump_->ScheduleWork();
340 } 340 }
341 } 341 }
342 342
343 bool MessageLoop::NestableTasksAllowed() const { 343 bool MessageLoop::NestableTasksAllowed() const {
344 return nestable_tasks_allowed_; 344 return nestable_tasks_allowed_;
345 } 345 }
346 346
347 bool MessageLoop::IsNested() { 347 bool MessageLoop::IsNested() {
348 return state_->run_depth > 1; 348 return run_loop_->run_depth_ > 1;
349 } 349 }
350 350
351 void MessageLoop::AddTaskObserver(TaskObserver* task_observer) { 351 void MessageLoop::AddTaskObserver(TaskObserver* task_observer) {
352 DCHECK_EQ(this, current()); 352 DCHECK_EQ(this, current());
353 task_observers_.AddObserver(task_observer); 353 task_observers_.AddObserver(task_observer);
354 } 354 }
355 355
356 void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) { 356 void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) {
357 DCHECK_EQ(this, current()); 357 DCHECK_EQ(this, current());
358 task_observers_.RemoveObserver(task_observer); 358 task_observers_.RemoveObserver(task_observer);
359 } 359 }
360 360
361 void MessageLoop::AssertIdle() const { 361 void MessageLoop::AssertIdle() const {
362 // We only check |incoming_queue_|, since we don't want to lock |work_queue_|. 362 // We only check |incoming_queue_|, since we don't want to lock |work_queue_|.
363 base::AutoLock lock(incoming_queue_lock_); 363 base::AutoLock lock(incoming_queue_lock_);
364 DCHECK(incoming_queue_.empty()); 364 DCHECK(incoming_queue_.empty());
365 } 365 }
366 366
367 bool MessageLoop::is_running() const { 367 bool MessageLoop::is_running() const {
368 DCHECK_EQ(this, current()); 368 DCHECK_EQ(this, current());
369 return state_ != NULL; 369 return run_loop_ != NULL;
370 } 370 }
371 371
372 //------------------------------------------------------------------------------ 372 //------------------------------------------------------------------------------
373 373
374 // Runs the loop in two different SEH modes: 374 // Runs the loop in two different SEH modes:
375 // enable_SEH_restoration_ = false : any unhandled exception goes to the last 375 // enable_SEH_restoration_ = false : any unhandled exception goes to the last
376 // one that calls SetUnhandledExceptionFilter(). 376 // one that calls SetUnhandledExceptionFilter().
377 // enable_SEH_restoration_ = true : any unhandled exception goes to the filter 377 // enable_SEH_restoration_ = true : any unhandled exception goes to the filter
378 // that was existed before the loop was run. 378 // that was existed before the loop was run.
379 void MessageLoop::RunHandler() { 379 void MessageLoop::RunHandler() {
(...skipping 17 matching lines...) Expand all
397 return; 397 return;
398 } 398 }
399 #endif 399 #endif
400 400
401 void MessageLoop::RunInternal() { 401 void MessageLoop::RunInternal() {
402 DCHECK_EQ(this, current()); 402 DCHECK_EQ(this, current());
403 403
404 StartHistogrammer(); 404 StartHistogrammer();
405 405
406 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) 406 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
407 if (state_->dispatcher && type() == TYPE_UI) { 407 if (run_loop_->dispatcher_ && type() == TYPE_UI) {
408 static_cast<base::MessagePumpForUI*>(pump_.get())-> 408 static_cast<base::MessagePumpForUI*>(pump_.get())->
409 RunWithDispatcher(this, state_->dispatcher); 409 RunWithDispatcher(this, run_loop_->dispatcher_);
410 return; 410 return;
411 } 411 }
412 #endif 412 #endif
413 413
414 pump_->Run(this); 414 pump_->Run(this);
415 } 415 }
416 416
417 bool MessageLoop::ProcessNextDelayedNonNestableTask() { 417 bool MessageLoop::ProcessNextDelayedNonNestableTask() {
418 if (state_->run_depth != 1) 418 if (run_loop_->run_depth_ != 1)
419 return false; 419 return false;
420 420
421 if (deferred_non_nestable_work_queue_.empty()) 421 if (deferred_non_nestable_work_queue_.empty())
422 return false; 422 return false;
423 423
424 PendingTask pending_task = deferred_non_nestable_work_queue_.front(); 424 PendingTask pending_task = deferred_non_nestable_work_queue_.front();
425 deferred_non_nestable_work_queue_.pop(); 425 deferred_non_nestable_work_queue_.pop();
426 426
427 RunTask(pending_task); 427 RunTask(pending_task);
428 return true; 428 return true;
(...skipping 27 matching lines...) Expand all
456 FOR_EACH_OBSERVER(TaskObserver, task_observers_, 456 FOR_EACH_OBSERVER(TaskObserver, task_observers_,
457 DidProcessTask(pending_task.time_posted)); 457 DidProcessTask(pending_task.time_posted));
458 458
459 tracked_objects::ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, 459 tracked_objects::ThreadData::TallyRunOnNamedThreadIfTracking(pending_task,
460 start_time, tracked_objects::ThreadData::NowForEndOfRun()); 460 start_time, tracked_objects::ThreadData::NowForEndOfRun());
461 461
462 nestable_tasks_allowed_ = true; 462 nestable_tasks_allowed_ = true;
463 } 463 }
464 464
465 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { 465 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) {
466 if (pending_task.nestable || state_->run_depth == 1) { 466 if (pending_task.nestable || run_loop_->run_depth_ == 1) {
467 RunTask(pending_task); 467 RunTask(pending_task);
468 // Show that we ran a task (Note: a new one might arrive as a 468 // Show that we ran a task (Note: a new one might arrive as a
469 // consequence!). 469 // consequence!).
470 return true; 470 return true;
471 } 471 }
472 472
473 // We couldn't run the task now because we're in a nested message loop 473 // We couldn't run the task now because we're in a nested message loop
474 // and the task isn't nestable. 474 // and the task isn't nestable.
475 deferred_non_nestable_work_queue_.push(pending_task); 475 deferred_non_nestable_work_queue_.push(pending_task);
476 return false; 476 return false;
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 if (!delayed_work_queue_.empty()) 678 if (!delayed_work_queue_.empty())
679 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time; 679 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
680 680
681 return DeferOrRunPendingTask(pending_task); 681 return DeferOrRunPendingTask(pending_task);
682 } 682 }
683 683
684 bool MessageLoop::DoIdleWork() { 684 bool MessageLoop::DoIdleWork() {
685 if (ProcessNextDelayedNonNestableTask()) 685 if (ProcessNextDelayedNonNestableTask())
686 return true; 686 return true;
687 687
688 if (state_->quit_received) 688 if (run_loop_->quit_when_idle_received_)
689 pump_->Quit(); 689 pump_->Quit();
690 690
691 return false; 691 return false;
692 } 692 }
693 693
694 void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here, 694 void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here,
695 void(*deleter)(const void*), 695 void(*deleter)(const void*),
696 const void* object) { 696 const void* object) {
697 PostNonNestableTask(from_here, base::Bind(deleter, object)); 697 PostNonNestableTask(from_here, base::Bind(deleter, object));
698 } 698 }
699 699
700 void MessageLoop::ReleaseSoonInternal( 700 void MessageLoop::ReleaseSoonInternal(
701 const tracked_objects::Location& from_here, 701 const tracked_objects::Location& from_here,
702 void(*releaser)(const void*), 702 void(*releaser)(const void*),
703 const void* object) { 703 const void* object) {
704 PostNonNestableTask(from_here, base::Bind(releaser, object)); 704 PostNonNestableTask(from_here, base::Bind(releaser, object));
705 } 705 }
706 706
707 //------------------------------------------------------------------------------ 707 //------------------------------------------------------------------------------
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 708 // MessageLoopForUI
733 709
734 #if defined(OS_WIN) 710 #if defined(OS_WIN)
735 void MessageLoopForUI::DidProcessMessage(const MSG& message) { 711 void MessageLoopForUI::DidProcessMessage(const MSG& message) {
736 pump_win()->DidProcessMessage(message); 712 pump_win()->DidProcessMessage(message);
737 } 713 }
738 #endif // defined(OS_WIN) 714 #endif // defined(OS_WIN)
739 715
740 #if defined(OS_ANDROID) 716 #if defined(OS_ANDROID)
741 void MessageLoopForUI::Start() { 717 void MessageLoopForUI::Start() {
742 // No Histogram support for UI message loop as it is managed by Java side 718 // No Histogram support for UI message loop as it is managed by Java side
743 static_cast<base::MessagePumpForUI*>(pump_.get())->Start(this); 719 static_cast<base::MessagePumpForUI*>(pump_.get())->Start(this);
744 } 720 }
745 #endif 721 #endif
746 722
747 #if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID) 723 #if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID)
748 void MessageLoopForUI::AddObserver(Observer* observer) { 724 void MessageLoopForUI::AddObserver(Observer* observer) {
749 pump_ui()->AddObserver(observer); 725 pump_ui()->AddObserver(observer);
750 } 726 }
751 727
752 void MessageLoopForUI::RemoveObserver(Observer* observer) { 728 void MessageLoopForUI::RemoveObserver(Observer* observer) {
753 pump_ui()->RemoveObserver(observer); 729 pump_ui()->RemoveObserver(observer);
754 } 730 }
755 731
756 void MessageLoopForUI::RunWithDispatcher(Dispatcher* dispatcher) {
757 AutoRunState save_state(this);
758 state_->dispatcher = dispatcher;
759 RunHandler();
760 }
761
762 void MessageLoopForUI::RunAllPendingWithDispatcher(Dispatcher* dispatcher) {
763 AutoRunState save_state(this);
764 state_->dispatcher = dispatcher;
765 state_->quit_received = true; // Means run until we would otherwise block.
766 RunHandler();
767 }
768
769 #endif // !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID) 732 #endif // !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID)
770 733
771 //------------------------------------------------------------------------------ 734 //------------------------------------------------------------------------------
772 // MessageLoopForIO 735 // MessageLoopForIO
773 736
774 #if defined(OS_WIN) 737 #if defined(OS_WIN)
775 738
776 void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) { 739 void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) {
777 pump_io()->RegisterIOHandler(file, handler); 740 pump_io()->RegisterIOHandler(file, handler);
778 } 741 }
(...skipping 11 matching lines...) Expand all
790 Watcher *delegate) { 753 Watcher *delegate) {
791 return pump_libevent()->WatchFileDescriptor( 754 return pump_libevent()->WatchFileDescriptor(
792 fd, 755 fd,
793 persistent, 756 persistent,
794 static_cast<base::MessagePumpLibevent::Mode>(mode), 757 static_cast<base::MessagePumpLibevent::Mode>(mode),
795 controller, 758 controller,
796 delegate); 759 delegate);
797 } 760 }
798 761
799 #endif 762 #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