1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/message_loop.h" 6 7 #include <algorithm> 8 9 #include "base/compiler_specific.h" 10 #include "base/lazy_instance.h" 11 #include "base/logging.h" 12 #include "base/message_pump_default.h" 13 #include "base/string_util.h" 14 #include "base/thread_local.h" 15 16 #if defined(OS_MACOSX) 17 #include "base/message_pump_mac.h" 18 #endif 19 #if defined(OS_POSIX) 20 #include "base/message_pump_libevent.h" 21 #include "base/third_party/valgrind/valgrind.h" 22 #endif 23 #if defined(OS_POSIX) && !defined(OS_MACOSX) 24 #include "base/message_pump_glib.h" 25 #endif 26 27 using base::Time; 28 using base::TimeDelta; 29 30 // A lazily created thread local storage for quick access to a thread's message 31 // loop, if one exists. This should be safe and free of static constructors. 32 static base::LazyInstance<base::ThreadLocalPointer<MessageLoop> > lazy_tls_ptr( 33 base::LINKER_INITIALIZED); 34 35 //------------------------------------------------------------------------------ 36 37 // Logical events for Histogram profiling. Run with -message-loop-histogrammer 38 // to get an accounting of messages and actions taken on each thread. 39 static const int kTaskRunEvent = 0x1; 40 static const int kTimerEvent = 0x2; 41 42 // Provide range of message IDs for use in histogramming and debug display. 43 static const int kLeastNonZeroMessageId = 1; 44 static const int kMaxMessageId = 1099; 45 static const int kNumberOfDistinctMessagesDisplayed = 1100; 46 47 //------------------------------------------------------------------------------ 48 49 #if defined(OS_WIN) 50 51 // Upon a SEH exception in this thread, it restores the original unhandled 52 // exception filter. 53 static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) { 54 ::SetUnhandledExceptionFilter(old_filter); 55 return EXCEPTION_CONTINUE_SEARCH; 56 } 57 58 // Retrieves a pointer to the current unhandled exception filter. There 59 // is no standalone getter method. 60 static LPTOP_LEVEL_EXCEPTION_FILTER GetTopSEHFilter() { 61 LPTOP_LEVEL_EXCEPTION_FILTER top_filter = NULL; 62 top_filter = ::SetUnhandledExceptionFilter(0); 63 ::SetUnhandledExceptionFilter(top_filter); 64 return top_filter; 65 } 66 67 #endif // defined(OS_WIN) 68 69 //------------------------------------------------------------------------------ 70 71 // static 72 MessageLoop* MessageLoop::current() { 73 // TODO(darin): sadly, we cannot enable this yet since people call us even 74 // when they have no intention of using us. 75 // DCHECK(loop) << "Ouch, did you forget to initialize me?"; 76 return lazy_tls_ptr.Pointer()->Get(); 77 } 78 79 MessageLoop::MessageLoop(Type type) 80 : type_(type), 81 nestable_tasks_allowed_(true), 82 exception_restoration_(false), 83 state_(NULL), 84 next_sequence_num_(0) { 85 DCHECK(!current()) << "should only have one message loop per thread"; 86 lazy_tls_ptr.Pointer()->Set(this); 87 88 #if defined(OS_WIN) 89 // TODO(rvargas): Get rid of the OS guards. 90 if (type_ == TYPE_DEFAULT) { 91 pump_ = new base::MessagePumpDefault(); 92 } else if (type_ == TYPE_IO) { 93 pump_ = new base::MessagePumpForIO(); 94 } else { 95 DCHECK(type_ == TYPE_UI); 96 pump_ = new base::MessagePumpForUI(); 97 } 98 #elif defined(OS_POSIX) 99 if (type_ == TYPE_UI) { 100 #if defined(OS_MACOSX) 101 pump_ = base::MessagePumpMac::Create(); 102 #else 103 pump_ = new base::MessagePumpForUI(); 104 #endif 105 } else if (type_ == TYPE_IO) { 106 pump_ = new base::MessagePumpLibevent(); 107 } else { 108 pump_ = new base::MessagePumpDefault(); 109 } 110 #endif // OS_POSIX 111 } 112 113 MessageLoop::~MessageLoop() { 114 DCHECK(this == current()); 115 116 // Let interested parties have one last shot at accessing this. 117 FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_, 118 WillDestroyCurrentMessageLoop()); 119 120 DCHECK(!state_); 121 122 // Clean up any unprocessed tasks, but take care: deleting a task could 123 // result in the addition of more tasks (e.g., via DeleteSoon). We set a 124 // limit on the number of times we will allow a deleted task to generate more 125 // tasks. Normally, we should only pass through this loop once or twice. If 126 // we end up hitting the loop limit, then it is probably due to one task that 127 // is being stubborn. Inspect the queues to see who is left. 128 bool did_work; 129 for (int i = 0; i < 100; ++i) { 130 DeletePendingTasks(); 131 ReloadWorkQueue(); 132 // If we end up with empty queues, then break out of the loop. 133 did_work = DeletePendingTasks(); 134 if (!did_work) 135 break; 136 } 137 DCHECK(!did_work); 138 139 // OK, now make it so that no one can find us. 140 lazy_tls_ptr.Pointer()->Set(NULL); 141 } 142 143 void MessageLoop::AddDestructionObserver(DestructionObserver *obs) { 144 DCHECK(this == current()); 145 destruction_observers_.AddObserver(obs); 146 } 147 148 void MessageLoop::RemoveDestructionObserver(DestructionObserver *obs) { 149 DCHECK(this == current()); 150 destruction_observers_.RemoveObserver(obs); 151 } 152 153 void MessageLoop::Run() { 154 AutoRunState save_state(this); 155 RunHandler(); 156 } 157 158 void MessageLoop::RunAllPending() { 159 AutoRunState save_state(this); 160 state_->quit_received = true; // Means run until we would otherwise block. 161 RunHandler(); 162 } 163 164 // Runs the loop in two different SEH modes: 165 // enable_SEH_restoration_ = false : any unhandled exception goes to the last 166 // one that calls SetUnhandledExceptionFilter(). 167 // enable_SEH_restoration_ = true : any unhandled exception goes to the filter 168 // that was existed before the loop was run. 169 void MessageLoop::RunHandler() { 170 #if defined(OS_WIN) 171 if (exception_restoration_) { 172 RunInternalInSEHFrame(); 173 return; 174 } 175 #endif 176 177 RunInternal(); 178 } 179 //------------------------------------------------------------------------------ 180 #if defined(OS_WIN) 181 __declspec(noinline) void MessageLoop::RunInternalInSEHFrame() { 182 LPTOP_LEVEL_EXCEPTION_FILTER current_filter = GetTopSEHFilter(); 183 __try { 184 RunInternal(); 185 } __except(SEHFilter(current_filter)) { 186 } 187 return; 188 } 189 #endif 190 //------------------------------------------------------------------------------ 191 192 void MessageLoop::RunInternal() { 193 DCHECK(this == current()); 194 195 StartHistogrammer(); 196 197 #if !defined(OS_MACOSX) 198 if (state_->dispatcher && type() == TYPE_UI) { 199 static_cast<base::MessagePumpForUI*>(pump_.get())-> 200 RunWithDispatcher(this, state_->dispatcher); 201 return; 202 } 203 #endif 204 205 pump_->Run(this); 206 } 207 208 //------------------------------------------------------------------------------ 209 // Wrapper functions for use in above message loop framework. 210 211 bool MessageLoop::ProcessNextDelayedNonNestableTask() { 212 if (state_->run_depth != 1) 213 return false; 214 215 if (deferred_non_nestable_work_queue_.empty()) 216 return false; 217 218 Task* task = deferred_non_nestable_work_queue_.front().task; 219 deferred_non_nestable_work_queue_.pop(); 220 221 RunTask(task); 222 return true; 223 } 224 225 //------------------------------------------------------------------------------ 226 227 void MessageLoop::Quit() { 228 DCHECK(current() == this); 229 if (state_) { 230 state_->quit_received = true; 231 } else { 232 NOTREACHED() << "Must be inside Run to call Quit"; 233 } 234 } 235 236 void MessageLoop::PostTask( 237 const tracked_objects::Location& from_here, Task* task) { 238 PostTask_Helper(from_here, task, 0, true); 239 } 240 241 void MessageLoop::PostDelayedTask( 242 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { 243 PostTask_Helper(from_here, task, delay_ms, true); 244 } 245 246 void MessageLoop::PostNonNestableTask( 247 const tracked_objects::Location& from_here, Task* task) { 248 PostTask_Helper(from_here, task, 0, false); 249 } 250 251 void MessageLoop::PostNonNestableDelayedTask( 252 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { 253 PostTask_Helper(from_here, task, delay_ms, false); 254 } 255 256 // Possibly called on a background thread! 257 void MessageLoop::PostTask_Helper( 258 const tracked_objects::Location& from_here, Task* task, int64 delay_ms, 259 bool nestable) { 260 task->SetBirthPlace(from_here); 261 262 PendingTask pending_task(task, nestable); 263 264 if (delay_ms > 0) { 265 pending_task.delayed_run_time = 266 Time::Now() + TimeDelta::FromMilliseconds(delay_ms); 267 } else { 268 DCHECK_EQ(delay_ms, 0) << "delay should not be negative"; 269 } 270 271 // Warning: Don't try to short-circuit, and handle this thread's tasks more 272 // directly, as it could starve handling of foreign threads. Put every task 273 // into this queue. 274 275 scoped_refptr<base::MessagePump> pump; 276 { 277 AutoLock locked(incoming_queue_lock_); 278 279 bool was_empty = incoming_queue_.empty(); 280 incoming_queue_.push(pending_task); 281 if (!was_empty) 282 return; // Someone else should have started the sub-pump. 283 284 pump = pump_; 285 } 286 // Since the incoming_queue_ may contain a task that destroys this message 287 // loop, we cannot exit incoming_queue_lock_ until we are done with |this|. 288 // We use a stack-based reference to the message pump so that we can call 289 // ScheduleWork outside of incoming_queue_lock_. 290 291 pump->ScheduleWork(); 292 } 293 294 void MessageLoop::SetNestableTasksAllowed(bool allowed) { 295 if (nestable_tasks_allowed_ != allowed) { 296 nestable_tasks_allowed_ = allowed; 297 if (!nestable_tasks_allowed_) 298 return; 299 // Start the native pump if we are not already pumping. 300 pump_->ScheduleWork(); 301 } 302 } 303 304 bool MessageLoop::NestableTasksAllowed() const { 305 return nestable_tasks_allowed_; 306 } 307 308 bool MessageLoop::IsNested() { 309 return state_->run_depth > 1; 310 } 311 312 //------------------------------------------------------------------------------ 313 314 void MessageLoop::RunTask(Task* task) { 315 DCHECK(nestable_tasks_allowed_); 316 // Execute the task and assume the worst: It is probably not reentrant. 317 nestable_tasks_allowed_ = false; 318 319 HistogramEvent(kTaskRunEvent); 320 task->Run(); 321 delete task; 322 323 nestable_tasks_allowed_ = true; 324 } 325 326 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { 327 if (pending_task.nestable || state_->run_depth == 1) { 328 RunTask(pending_task.task); 329 // Show that we ran a task (Note: a new one might arrive as a 330 // consequence!). 331 return true; 332 } 333 334 // We couldn't run the task now because we're in a nested message loop 335 // and the task isn't nestable. 336 deferred_non_nestable_work_queue_.push(pending_task); 337 return false; 338 } 339 340 void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) { 341 // Move to the delayed work queue. Initialize the sequence number 342 // before inserting into the delayed_work_queue_. The sequence number 343 // is used to faciliate FIFO sorting when two tasks have the same 344 // delayed_run_time value. 345 PendingTask new_pending_task(pending_task); 346 new_pending_task.sequence_num = next_sequence_num_++; 347 delayed_work_queue_.push(new_pending_task); 348 } 349 350 void MessageLoop::ReloadWorkQueue() { 351 // We can improve performance of our loading tasks from incoming_queue_ to 352 // work_queue_ by waiting until the last minute (work_queue_ is empty) to 353 // load. That reduces the number of locks-per-task significantly when our 354 // queues get large. 355 if (!work_queue_.empty()) 356 return; // Wait till we *really* need to lock and load. 357 358 // Acquire all we can from the inter-thread queue with one lock acquisition. 359 { 360 AutoLock lock(incoming_queue_lock_); 361 if (incoming_queue_.empty()) 362 return; 363 incoming_queue_.Swap(&work_queue_); // Constant time 364 DCHECK(incoming_queue_.empty()); 365 } 366 } 367 368 bool MessageLoop::DeletePendingTasks() { 369 bool did_work = !work_queue_.empty(); 370 while (!work_queue_.empty()) { 371 PendingTask pending_task = work_queue_.front(); 372 work_queue_.pop(); 373 if (!pending_task.delayed_run_time.is_null()) { 374 // We want to delete delayed tasks in the same order in which they would 375 // normally be deleted in case of any funny dependencies between delayed 376 // tasks. 377 AddToDelayedWorkQueue(pending_task); 378 } else { 379 // TODO(darin): Delete all tasks once it is safe to do so. 380 // Until it is totally safe, just do it when running Purify or 381 // Valgrind. 382 #if defined(PURIFY) 383 delete pending_task.task; 384 #elif defined(OS_POSIX) 385 if (RUNNING_ON_VALGRIND) 386 delete pending_task.task; 387 #endif // defined(OS_POSIX) 388 } 389 } 390 did_work |= !deferred_non_nestable_work_queue_.empty(); 391 while (!deferred_non_nestable_work_queue_.empty()) { 392 // TODO(darin): Delete all tasks once it is safe to do so. 393 // Until it is totaly safe, only delete them under Purify and Valgrind. 394 Task* task = NULL; 395 #if defined(PURIFY) 396 task = deferred_non_nestable_work_queue_.front().task; 397 #elif defined(OS_POSIX) 398 if (RUNNING_ON_VALGRIND) 399 task = deferred_non_nestable_work_queue_.front().task; 400 #endif 401 deferred_non_nestable_work_queue_.pop(); 402 if (task) 403 delete task; 404 } 405 did_work |= !delayed_work_queue_.empty(); 406 while (!delayed_work_queue_.empty()) { 407 Task* task = delayed_work_queue_.top().task; 408 delayed_work_queue_.pop(); 409 delete task; 410 } 411 return did_work; 412 } 413 414 bool MessageLoop::DoWork() { 415 if (!nestable_tasks_allowed_) { 416 // Task can't be executed right now. 417 return false; 418 } 419 420 for (;;) { 421 ReloadWorkQueue(); 422 if (work_queue_.empty()) 423 break; 424 425 // Execute oldest task. 426 do { 427 PendingTask pending_task = work_queue_.front(); 428 work_queue_.pop(); 429 if (!pending_task.delayed_run_time.is_null()) { 430 AddToDelayedWorkQueue(pending_task); 431 // If we changed the topmost task, then it is time to re-schedule. 432 if (delayed_work_queue_.top().task == pending_task.task) 433 pump_->ScheduleDelayedWork(pending_task.delayed_run_time); 434 } else { 435 if (DeferOrRunPendingTask(pending_task)) 436 return true; 437 } 438 } while (!work_queue_.empty()); 439 } 440 441 // Nothing happened. 442 return false; 443 } 444 445 bool MessageLoop::DoDelayedWork(Time* next_delayed_work_time) { 446 if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) { 447 *next_delayed_work_time = Time(); 448 return false; 449 } 450 451 if (delayed_work_queue_.top().delayed_run_time > Time::Now()) { 452 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time; 453 return false; 454 } 455 456 PendingTask pending_task = delayed_work_queue_.top(); 457 delayed_work_queue_.pop(); 458 459 if (!delayed_work_queue_.empty()) 460 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time; 461 462 return DeferOrRunPendingTask(pending_task); 463 } 464 465 bool MessageLoop::DoIdleWork() { 466 if (ProcessNextDelayedNonNestableTask()) 467 return true; 468 469 if (state_->quit_received) 470 pump_->Quit(); 471 472 return false; 473 } 474 475 //------------------------------------------------------------------------------ 476 // MessageLoop::AutoRunState 477 478 MessageLoop::AutoRunState::AutoRunState(MessageLoop* loop) : loop_(loop) { 479 // Make the loop reference us. 480 previous_state_ = loop_->state_; 481 if (previous_state_) { 482 run_depth = previous_state_->run_depth + 1; 483 } else { 484 run_depth = 1; 485 } 486 loop_->state_ = this; 487 488 // Initialize the other fields: 489 quit_received = false; 490 #if !defined(OS_MACOSX) 491 dispatcher = NULL; 492 #endif 493 } 494 495 MessageLoop::AutoRunState::~AutoRunState() { 496 loop_->state_ = previous_state_; 497 } 498 499 //------------------------------------------------------------------------------ 500 // MessageLoop::PendingTask 501 502 bool MessageLoop::PendingTask::operator<(const PendingTask& other) const { 503 // Since the top of a priority queue is defined as the "greatest" element, we 504 // need to invert the comparison here. We want the smaller time to be at the 505 // top of the heap. 506 507 if (delayed_run_time < other.delayed_run_time) 508 return false; 509 510 if (delayed_run_time > other.delayed_run_time) 511 return true; 512 513 // If the times happen to match, then we use the sequence number to decide. 514 // Compare the difference to support integer roll-over. 515 return (sequence_num - other.sequence_num) > 0; 516 } 517 518 //------------------------------------------------------------------------------ 519 // Method and data for histogramming events and actions taken by each instance 520 // on each thread. 521 522 // static 523 bool MessageLoop::enable_histogrammer_ = false; 524 525 // static 526 void MessageLoop::EnableHistogrammer(bool enable) { 527 enable_histogrammer_ = enable; 528 } 529 530 void MessageLoop::StartHistogrammer() { 531 if (enable_histogrammer_ && !message_histogram_.get() 532 && StatisticsRecorder::WasStarted()) { 533 DCHECK(!thread_name_.empty()); 534 message_histogram_ = LinearHistogram::FactoryGet("MsgLoop:" + thread_name_, 535 kLeastNonZeroMessageId, kMaxMessageId, 536 kNumberOfDistinctMessagesDisplayed, 537 message_histogram_->kHexRangePrintingFlag); 538 message_histogram_->SetRangeDescriptions(event_descriptions_); 539 } 540 } 541 542 void MessageLoop::HistogramEvent(int event) { 543 if (message_histogram_.get()) 544 message_histogram_->Add(event); 545 } 546 547 // Provide a macro that takes an expression (such as a constant, or macro 548 // constant) and creates a pair to initalize an array of pairs. In this case, 549 // our pair consists of the expressions value, and the "stringized" version 550 // of the expression (i.e., the exrpression put in quotes). For example, if 551 // we have: 552 // #define FOO 2 553 // #define BAR 5 554 // then the following: 555 // VALUE_TO_NUMBER_AND_NAME(FOO + BAR) 556 // will expand to: 557 // {7, "FOO + BAR"} 558 // We use the resulting array as an argument to our histogram, which reads the 559 // number as a bucket identifier, and proceeds to use the corresponding name 560 // in the pair (i.e., the quoted string) when printing out a histogram. 561 #define VALUE_TO_NUMBER_AND_NAME(name) {name, #name}, 562 563 // static 564 const LinearHistogram::DescriptionPair MessageLoop::event_descriptions_[] = { 565 // Provide some pretty print capability in our histogram for our internal 566 // messages. 567 568 // A few events we handle (kindred to messages), and used to profile actions. 569 VALUE_TO_NUMBER_AND_NAME(kTaskRunEvent) 570 VALUE_TO_NUMBER_AND_NAME(kTimerEvent) 571 572 {-1, NULL} // The list must be null terminated, per API to histogram. 573 }; 574 575 //------------------------------------------------------------------------------ 576 // MessageLoopForUI 577 578 #if defined(OS_WIN) 579 void MessageLoopForUI::WillProcessMessage(const MSG& message) { 580 pump_win()->WillProcessMessage(message); 581 } 582 void MessageLoopForUI::DidProcessMessage(const MSG& message) { 583 pump_win()->DidProcessMessage(message); 584 } 585 void MessageLoopForUI::PumpOutPendingPaintMessages() { 586 pump_ui()->PumpOutPendingPaintMessages(); 587 } 588 589 #endif // defined(OS_WIN) 590 591 #if !defined(OS_MACOSX) 592 void MessageLoopForUI::AddObserver(Observer* observer) { 593 pump_ui()->AddObserver(observer); 594 } 595 596 void MessageLoopForUI::RemoveObserver(Observer* observer) { 597 pump_ui()->RemoveObserver(observer); 598 } 599 600 void MessageLoopForUI::Run(Dispatcher* dispatcher) { 601 AutoRunState save_state(this); 602 state_->dispatcher = dispatcher; 603 RunHandler(); 604 } 605 #endif // !defined(OS_MACOSX) 606 607 //------------------------------------------------------------------------------ 608 // MessageLoopForIO 609 610 #if defined(OS_WIN) 611 612 void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) { 613 pump_io()->RegisterIOHandler(file, handler); 614 } 615 616 bool MessageLoopForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) { 617 return pump_io()->WaitForIOCompletion(timeout, filter); 618 } 619 620 #elif defined(OS_POSIX) 621 622 bool MessageLoopForIO::WatchFileDescriptor(int fd, 623 bool persistent, 624 Mode mode, 625 FileDescriptorWatcher *controller, 626 Watcher *delegate) { 627 return pump_libevent()->WatchFileDescriptor( 628 fd, 629 persistent, 630 static_cast<base::MessagePumpLibevent::Mode>(mode), 631 controller, 632 delegate); 633 } 634 635 #endif 636