| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #if defined(OS_POSIX) && !defined(OS_MACOSX) | |
| 8 #include <gdk/gdk.h> | |
| 9 #include <gdk/gdkx.h> | |
| 10 #endif | |
| 11 | |
| 12 #include <algorithm> | 7 #include <algorithm> |
| 13 | 8 |
| 9 #include "base/bind.h" |
| 14 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| 15 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
| 16 #include "base/logging.h" | 12 #include "base/logging.h" |
| 17 #include "base/message_pump_default.h" | 13 #include "base/message_pump_default.h" |
| 18 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/scoped_ptr.h" |
| 19 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 16 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
| 20 #include "base/threading/thread_local.h" | 17 #include "base/threading/thread_local.h" |
| 18 #include "base/tracked_objects.h" |
| 21 | 19 |
| 22 #if defined(OS_MACOSX) | 20 #if defined(OS_MACOSX) |
| 23 #include "base/message_pump_mac.h" | 21 #include "base/message_pump_mac.h" |
| 24 #endif | 22 #endif |
| 25 #if defined(OS_POSIX) | 23 #if defined(OS_POSIX) |
| 26 #include "base/message_pump_libevent.h" | 24 #include "base/message_pump_libevent.h" |
| 27 #endif | 25 #endif |
| 28 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 26 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
| 27 #include <gdk/gdk.h> |
| 28 #include <gdk/gdkx.h> |
| 29 #include "base/message_pump_glib.h" | 29 #include "base/message_pump_glib.h" |
| 30 #endif | 30 #endif |
| 31 #if defined(TOUCH_UI) | 31 #if defined(TOUCH_UI) |
| 32 #include "base/message_pump_glib_x.h" | 32 #include "base/message_pump_glib_x.h" |
| 33 #endif | 33 #endif |
| 34 | 34 |
| 35 using base::TimeDelta; | 35 using base::TimeDelta; |
| 36 using base::TimeTicks; | 36 using base::TimeTicks; |
| 37 | 37 |
| 38 namespace { | 38 namespace { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 | 74 |
| 75 // A few events we handle (kindred to messages), and used to profile actions. | 75 // A few events we handle (kindred to messages), and used to profile actions. |
| 76 VALUE_TO_NUMBER_AND_NAME(kTaskRunEvent) | 76 VALUE_TO_NUMBER_AND_NAME(kTaskRunEvent) |
| 77 VALUE_TO_NUMBER_AND_NAME(kTimerEvent) | 77 VALUE_TO_NUMBER_AND_NAME(kTimerEvent) |
| 78 | 78 |
| 79 {-1, NULL} // The list must be null terminated, per API to histogram. | 79 {-1, NULL} // The list must be null terminated, per API to histogram. |
| 80 }; | 80 }; |
| 81 | 81 |
| 82 bool enable_histogrammer_ = false; | 82 bool enable_histogrammer_ = false; |
| 83 | 83 |
| 84 // TODO(ajwong): This is one use case for having a Owned() tag that behaves |
| 85 // like a "Unique" pointer. If we had that, and Tasks were always safe to |
| 86 // delete on MessageLoop shutdown, this class could just be a function. |
| 87 class TaskClosureAdapter : public base::RefCounted<TaskClosureAdapter> { |
| 88 public: |
| 89 // |should_leak_task| points to a flag variable that can be used to determine |
| 90 // if this class should leak the Task on destruction. This is important |
| 91 // at MessageLoop shutdown since not all tasks can be safely deleted without |
| 92 // running. See MessageLoop::DeletePendingTasks() for the exact behavior |
| 93 // of when a Task should be deleted. It is subtle. |
| 94 TaskClosureAdapter(Task* task, bool* should_leak_task) |
| 95 : task_(task), |
| 96 should_leak_task_(should_leak_task) { |
| 97 } |
| 98 |
| 99 void Run() { |
| 100 task_->Run(); |
| 101 delete task_; |
| 102 task_ = NULL; |
| 103 } |
| 104 |
| 105 private: |
| 106 friend class base::RefCounted<TaskClosureAdapter>; |
| 107 |
| 108 ~TaskClosureAdapter() { |
| 109 if (!*should_leak_task_) { |
| 110 delete task_; |
| 111 } |
| 112 } |
| 113 |
| 114 Task* task_; |
| 115 bool* should_leak_task_; |
| 116 }; |
| 117 |
| 84 } // namespace | 118 } // namespace |
| 85 | 119 |
| 86 //------------------------------------------------------------------------------ | 120 //------------------------------------------------------------------------------ |
| 87 | 121 |
| 88 #if defined(OS_WIN) | 122 #if defined(OS_WIN) |
| 89 | 123 |
| 90 // Upon a SEH exception in this thread, it restores the original unhandled | 124 // Upon a SEH exception in this thread, it restores the original unhandled |
| 91 // exception filter. | 125 // exception filter. |
| 92 static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) { | 126 static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) { |
| 93 ::SetUnhandledExceptionFilter(old_filter); | 127 ::SetUnhandledExceptionFilter(old_filter); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 117 } | 151 } |
| 118 | 152 |
| 119 //------------------------------------------------------------------------------ | 153 //------------------------------------------------------------------------------ |
| 120 | 154 |
| 121 MessageLoop::MessageLoop(Type type) | 155 MessageLoop::MessageLoop(Type type) |
| 122 : type_(type), | 156 : type_(type), |
| 123 nestable_tasks_allowed_(true), | 157 nestable_tasks_allowed_(true), |
| 124 exception_restoration_(false), | 158 exception_restoration_(false), |
| 125 message_histogram_(NULL), | 159 message_histogram_(NULL), |
| 126 state_(NULL), | 160 state_(NULL), |
| 161 should_leak_tasks_(true), |
| 127 #ifdef OS_WIN | 162 #ifdef OS_WIN |
| 128 os_modal_loop_(false), | 163 os_modal_loop_(false), |
| 129 #endif // OS_WIN | 164 #endif // OS_WIN |
| 130 next_sequence_num_(0) { | 165 next_sequence_num_(0) { |
| 131 DCHECK(!current()) << "should only have one message loop per thread"; | 166 DCHECK(!current()) << "should only have one message loop per thread"; |
| 132 lazy_tls_ptr.Pointer()->Set(this); | 167 lazy_tls_ptr.Pointer()->Set(this); |
| 133 | 168 |
| 134 // TODO(rvargas): Get rid of the OS guards. | 169 // TODO(rvargas): Get rid of the OS guards. |
| 135 #if defined(OS_WIN) | 170 #if defined(OS_WIN) |
| 136 #define MESSAGE_PUMP_UI new base::MessagePumpForUI() | 171 #define MESSAGE_PUMP_UI new base::MessagePumpForUI() |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 } | 248 } |
| 214 | 249 |
| 215 void MessageLoop::RemoveDestructionObserver( | 250 void MessageLoop::RemoveDestructionObserver( |
| 216 DestructionObserver* destruction_observer) { | 251 DestructionObserver* destruction_observer) { |
| 217 DCHECK_EQ(this, current()); | 252 DCHECK_EQ(this, current()); |
| 218 destruction_observers_.RemoveObserver(destruction_observer); | 253 destruction_observers_.RemoveObserver(destruction_observer); |
| 219 } | 254 } |
| 220 | 255 |
| 221 void MessageLoop::PostTask( | 256 void MessageLoop::PostTask( |
| 222 const tracked_objects::Location& from_here, Task* task) { | 257 const tracked_objects::Location& from_here, Task* task) { |
| 223 PostTask_Helper(from_here, task, 0, true); | 258 PendingTask pending_task( |
| 259 base::Bind(&TaskClosureAdapter::Run, |
| 260 new TaskClosureAdapter(task, &should_leak_tasks_)), |
| 261 from_here, |
| 262 CalculateDelayedRuntime(0), true); |
| 263 AddToIncomingQueue(&pending_task); |
| 224 } | 264 } |
| 225 | 265 |
| 226 void MessageLoop::PostDelayedTask( | 266 void MessageLoop::PostDelayedTask( |
| 227 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { | 267 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { |
| 228 PostTask_Helper(from_here, task, delay_ms, true); | 268 PendingTask pending_task( |
| 269 base::Bind(&TaskClosureAdapter::Run, |
| 270 new TaskClosureAdapter(task, &should_leak_tasks_)), |
| 271 from_here, |
| 272 CalculateDelayedRuntime(delay_ms), true); |
| 273 AddToIncomingQueue(&pending_task); |
| 229 } | 274 } |
| 230 | 275 |
| 231 void MessageLoop::PostNonNestableTask( | 276 void MessageLoop::PostNonNestableTask( |
| 232 const tracked_objects::Location& from_here, Task* task) { | 277 const tracked_objects::Location& from_here, Task* task) { |
| 233 PostTask_Helper(from_here, task, 0, false); | 278 PendingTask pending_task( |
| 279 base::Bind(&TaskClosureAdapter::Run, |
| 280 new TaskClosureAdapter(task, &should_leak_tasks_)), |
| 281 from_here, |
| 282 CalculateDelayedRuntime(0), false); |
| 283 AddToIncomingQueue(&pending_task); |
| 234 } | 284 } |
| 235 | 285 |
| 236 void MessageLoop::PostNonNestableDelayedTask( | 286 void MessageLoop::PostNonNestableDelayedTask( |
| 237 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { | 287 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { |
| 238 PostTask_Helper(from_here, task, delay_ms, false); | 288 PendingTask pending_task( |
| 289 base::Bind(&TaskClosureAdapter::Run, |
| 290 new TaskClosureAdapter(task, &should_leak_tasks_)), |
| 291 from_here, |
| 292 CalculateDelayedRuntime(delay_ms), false); |
| 293 AddToIncomingQueue(&pending_task); |
| 294 } |
| 295 |
| 296 void MessageLoop::PostTask( |
| 297 const tracked_objects::Location& from_here, const base::Closure& task) { |
| 298 DCHECK(!task.is_null()); |
| 299 PendingTask pending_task(task, from_here, CalculateDelayedRuntime(0), true); |
| 300 AddToIncomingQueue(&pending_task); |
| 301 } |
| 302 |
| 303 void MessageLoop::PostDelayedTask( |
| 304 const tracked_objects::Location& from_here, const base::Closure& task, |
| 305 int64 delay_ms) { |
| 306 DCHECK(!task.is_null()); |
| 307 PendingTask pending_task(task, from_here, |
| 308 CalculateDelayedRuntime(delay_ms), true); |
| 309 AddToIncomingQueue(&pending_task); |
| 310 } |
| 311 |
| 312 void MessageLoop::PostNonNestableTask( |
| 313 const tracked_objects::Location& from_here, const base::Closure& task) { |
| 314 DCHECK(!task.is_null()); |
| 315 PendingTask pending_task(task, from_here, CalculateDelayedRuntime(0), false); |
| 316 AddToIncomingQueue(&pending_task); |
| 317 } |
| 318 |
| 319 void MessageLoop::PostNonNestableDelayedTask( |
| 320 const tracked_objects::Location& from_here, const base::Closure& task, |
| 321 int64 delay_ms) { |
| 322 DCHECK(!task.is_null()); |
| 323 PendingTask pending_task(task, from_here, |
| 324 CalculateDelayedRuntime(delay_ms), false); |
| 325 AddToIncomingQueue(&pending_task); |
| 239 } | 326 } |
| 240 | 327 |
| 241 void MessageLoop::Run() { | 328 void MessageLoop::Run() { |
| 242 AutoRunState save_state(this); | 329 AutoRunState save_state(this); |
| 243 RunHandler(); | 330 RunHandler(); |
| 244 } | 331 } |
| 245 | 332 |
| 246 void MessageLoop::RunAllPending() { | 333 void MessageLoop::RunAllPending() { |
| 247 AutoRunState save_state(this); | 334 AutoRunState save_state(this); |
| 248 state_->quit_received = true; // Means run until we would otherwise block. | 335 state_->quit_received = true; // Means run until we would otherwise block. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 pump_->Run(this); | 433 pump_->Run(this); |
| 347 } | 434 } |
| 348 | 435 |
| 349 bool MessageLoop::ProcessNextDelayedNonNestableTask() { | 436 bool MessageLoop::ProcessNextDelayedNonNestableTask() { |
| 350 if (state_->run_depth != 1) | 437 if (state_->run_depth != 1) |
| 351 return false; | 438 return false; |
| 352 | 439 |
| 353 if (deferred_non_nestable_work_queue_.empty()) | 440 if (deferred_non_nestable_work_queue_.empty()) |
| 354 return false; | 441 return false; |
| 355 | 442 |
| 356 Task* task = deferred_non_nestable_work_queue_.front().task; | 443 PendingTask pending_task = deferred_non_nestable_work_queue_.front(); |
| 357 deferred_non_nestable_work_queue_.pop(); | 444 deferred_non_nestable_work_queue_.pop(); |
| 358 | 445 |
| 359 RunTask(task); | 446 RunTask(pending_task); |
| 360 return true; | 447 return true; |
| 361 } | 448 } |
| 362 | 449 |
| 363 void MessageLoop::RunTask(Task* task) { | 450 void MessageLoop::RunTask(const PendingTask& pending_task) { |
| 364 DCHECK(nestable_tasks_allowed_); | 451 DCHECK(nestable_tasks_allowed_); |
| 365 // Execute the task and assume the worst: It is probably not reentrant. | 452 // Execute the task and assume the worst: It is probably not reentrant. |
| 366 nestable_tasks_allowed_ = false; | 453 nestable_tasks_allowed_ = false; |
| 367 | 454 |
| 368 HistogramEvent(kTaskRunEvent); | 455 HistogramEvent(kTaskRunEvent); |
| 369 FOR_EACH_OBSERVER(TaskObserver, task_observers_, | 456 FOR_EACH_OBSERVER(TaskObserver, task_observers_, |
| 370 WillProcessTask(task)); | 457 WillProcessTask(pending_task.time_posted)); |
| 371 task->Run(); | 458 pending_task.task.Run(); |
| 372 FOR_EACH_OBSERVER(TaskObserver, task_observers_, DidProcessTask(task)); | 459 FOR_EACH_OBSERVER(TaskObserver, task_observers_, |
| 373 delete task; | 460 DidProcessTask(pending_task.time_posted)); |
| 461 |
| 462 #if defined(TRACK_ALL_TASK_OBJECTS) |
| 463 if (tracked_objects::ThreadData::IsActive() && pending_task.post_births) { |
| 464 tracked_objects::ThreadData::current()->TallyADeath( |
| 465 *pending_task.post_births, |
| 466 TimeTicks::Now() - pending_task.time_posted); |
| 467 } |
| 468 #endif // defined(TRACK_ALL_TASK_OBJECTS) |
| 374 | 469 |
| 375 nestable_tasks_allowed_ = true; | 470 nestable_tasks_allowed_ = true; |
| 376 } | 471 } |
| 377 | 472 |
| 378 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { | 473 bool MessageLoop::DeferOrRunPendingTask( |
| 474 const PendingTask& pending_task) { |
| 379 if (pending_task.nestable || state_->run_depth == 1) { | 475 if (pending_task.nestable || state_->run_depth == 1) { |
| 380 RunTask(pending_task.task); | 476 RunTask(pending_task); |
| 381 // Show that we ran a task (Note: a new one might arrive as a | 477 // Show that we ran a task (Note: a new one might arrive as a |
| 382 // consequence!). | 478 // consequence!). |
| 383 return true; | 479 return true; |
| 384 } | 480 } |
| 385 | 481 |
| 386 // We couldn't run the task now because we're in a nested message loop | 482 // We couldn't run the task now because we're in a nested message loop |
| 387 // and the task isn't nestable. | 483 // and the task isn't nestable. |
| 388 deferred_non_nestable_work_queue_.push(pending_task); | 484 deferred_non_nestable_work_queue_.push(pending_task); |
| 389 return false; | 485 return false; |
| 390 } | 486 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 412 base::AutoLock lock(incoming_queue_lock_); | 508 base::AutoLock lock(incoming_queue_lock_); |
| 413 if (incoming_queue_.empty()) | 509 if (incoming_queue_.empty()) |
| 414 return; | 510 return; |
| 415 incoming_queue_.Swap(&work_queue_); // Constant time | 511 incoming_queue_.Swap(&work_queue_); // Constant time |
| 416 DCHECK(incoming_queue_.empty()); | 512 DCHECK(incoming_queue_.empty()); |
| 417 } | 513 } |
| 418 } | 514 } |
| 419 | 515 |
| 420 bool MessageLoop::DeletePendingTasks() { | 516 bool MessageLoop::DeletePendingTasks() { |
| 421 bool did_work = !work_queue_.empty(); | 517 bool did_work = !work_queue_.empty(); |
| 518 // TODO(darin): Delete all tasks once it is safe to do so. |
| 519 // Until it is totally safe, just do it when running Purify or |
| 520 // Valgrind. |
| 521 // |
| 522 // See http://crbug.com/61131 |
| 523 // |
| 524 #if defined(PURIFY) || defined(USE_HEAPCHECKER) |
| 525 should_leak_tasks_ = false; |
| 526 #else |
| 527 if (RunningOnValgrind()) |
| 528 should_leak_tasks_ = false; |
| 529 #endif // defined(OS_POSIX) |
| 422 while (!work_queue_.empty()) { | 530 while (!work_queue_.empty()) { |
| 423 PendingTask pending_task = work_queue_.front(); | 531 PendingTask pending_task = work_queue_.front(); |
| 424 work_queue_.pop(); | 532 work_queue_.pop(); |
| 425 if (!pending_task.delayed_run_time.is_null()) { | 533 if (!pending_task.delayed_run_time.is_null()) { |
| 426 // We want to delete delayed tasks in the same order in which they would | 534 // We want to delete delayed tasks in the same order in which they would |
| 427 // normally be deleted in case of any funny dependencies between delayed | 535 // normally be deleted in case of any funny dependencies between delayed |
| 428 // tasks. | 536 // tasks. |
| 429 AddToDelayedWorkQueue(pending_task); | 537 AddToDelayedWorkQueue(pending_task); |
| 430 } else { | |
| 431 // TODO(darin): Delete all tasks once it is safe to do so. | |
| 432 // Until it is totally safe, just do it when running Purify or | |
| 433 // Valgrind. | |
| 434 #if defined(PURIFY) || defined(USE_HEAPCHECKER) | |
| 435 delete pending_task.task; | |
| 436 #else | |
| 437 if (RunningOnValgrind()) | |
| 438 delete pending_task.task; | |
| 439 #endif // defined(OS_POSIX) | |
| 440 } | 538 } |
| 441 } | 539 } |
| 442 did_work |= !deferred_non_nestable_work_queue_.empty(); | 540 did_work |= !deferred_non_nestable_work_queue_.empty(); |
| 443 while (!deferred_non_nestable_work_queue_.empty()) { | 541 while (!deferred_non_nestable_work_queue_.empty()) { |
| 444 // TODO(darin): Delete all tasks once it is safe to do so. | |
| 445 // Until it is totaly safe, only delete them under Purify and Valgrind. | |
| 446 Task* task = NULL; | |
| 447 #if defined(PURIFY) || defined(USE_HEAPCHECKER) | |
| 448 task = deferred_non_nestable_work_queue_.front().task; | |
| 449 #else | |
| 450 if (RunningOnValgrind()) | |
| 451 task = deferred_non_nestable_work_queue_.front().task; | |
| 452 #endif | |
| 453 deferred_non_nestable_work_queue_.pop(); | 542 deferred_non_nestable_work_queue_.pop(); |
| 454 if (task) | |
| 455 delete task; | |
| 456 } | 543 } |
| 457 did_work |= !delayed_work_queue_.empty(); | 544 did_work |= !delayed_work_queue_.empty(); |
| 545 |
| 546 // Historically, we always delete the task regardless of valgrind status. It's |
| 547 // not completely clear why we want to leak them in the loops above. This |
| 548 // code is replicating legacy behavior, and should not be considered |
| 549 // absolutely "correct" behavior. See TODO above about deleting all tasks |
| 550 // when it's safe. |
| 551 should_leak_tasks_ = false; |
| 458 while (!delayed_work_queue_.empty()) { | 552 while (!delayed_work_queue_.empty()) { |
| 459 Task* task = delayed_work_queue_.top().task; | |
| 460 delayed_work_queue_.pop(); | 553 delayed_work_queue_.pop(); |
| 461 delete task; | |
| 462 } | 554 } |
| 555 should_leak_tasks_ = true; |
| 463 return did_work; | 556 return did_work; |
| 464 } | 557 } |
| 465 | 558 |
| 466 // Possibly called on a background thread! | 559 TimeTicks MessageLoop::CalculateDelayedRuntime(int64 delay_ms) { |
| 467 void MessageLoop::PostTask_Helper( | 560 TimeTicks delayed_run_time; |
| 468 const tracked_objects::Location& from_here, Task* task, int64 delay_ms, | |
| 469 bool nestable) { | |
| 470 task->SetBirthPlace(from_here); | |
| 471 | |
| 472 PendingTask pending_task(task, nestable); | |
| 473 | |
| 474 if (delay_ms > 0) { | 561 if (delay_ms > 0) { |
| 475 pending_task.delayed_run_time = | 562 delayed_run_time = |
| 476 TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms); | 563 TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms); |
| 477 | 564 |
| 478 #if defined(OS_WIN) | 565 #if defined(OS_WIN) |
| 479 if (high_resolution_timer_expiration_.is_null()) { | 566 if (high_resolution_timer_expiration_.is_null()) { |
| 480 // Windows timers are granular to 15.6ms. If we only set high-res | 567 // Windows timers are granular to 15.6ms. If we only set high-res |
| 481 // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms, | 568 // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms, |
| 482 // which as a percentage is pretty inaccurate. So enable high | 569 // which as a percentage is pretty inaccurate. So enable high |
| 483 // res timers for any timer which is within 2x of the granularity. | 570 // res timers for any timer which is within 2x of the granularity. |
| 484 // This is a tradeoff between accuracy and power management. | 571 // This is a tradeoff between accuracy and power management. |
| 485 bool needs_high_res_timers = | 572 bool needs_high_res_timers = |
| (...skipping 11 matching lines...) Expand all Loading... |
| 497 | 584 |
| 498 #if defined(OS_WIN) | 585 #if defined(OS_WIN) |
| 499 if (!high_resolution_timer_expiration_.is_null()) { | 586 if (!high_resolution_timer_expiration_.is_null()) { |
| 500 if (TimeTicks::Now() > high_resolution_timer_expiration_) { | 587 if (TimeTicks::Now() > high_resolution_timer_expiration_) { |
| 501 base::Time::ActivateHighResolutionTimer(false); | 588 base::Time::ActivateHighResolutionTimer(false); |
| 502 high_resolution_timer_expiration_ = TimeTicks(); | 589 high_resolution_timer_expiration_ = TimeTicks(); |
| 503 } | 590 } |
| 504 } | 591 } |
| 505 #endif | 592 #endif |
| 506 | 593 |
| 594 return delayed_run_time; |
| 595 } |
| 596 |
| 597 // Possibly called on a background thread! |
| 598 void MessageLoop::AddToIncomingQueue(PendingTask* pending_task) { |
| 507 // Warning: Don't try to short-circuit, and handle this thread's tasks more | 599 // Warning: Don't try to short-circuit, and handle this thread's tasks more |
| 508 // directly, as it could starve handling of foreign threads. Put every task | 600 // directly, as it could starve handling of foreign threads. Put every task |
| 509 // into this queue. | 601 // into this queue. |
| 510 | 602 |
| 511 scoped_refptr<base::MessagePump> pump; | 603 scoped_refptr<base::MessagePump> pump; |
| 512 { | 604 { |
| 513 base::AutoLock locked(incoming_queue_lock_); | 605 base::AutoLock locked(incoming_queue_lock_); |
| 514 | 606 |
| 515 bool was_empty = incoming_queue_.empty(); | 607 bool was_empty = incoming_queue_.empty(); |
| 516 incoming_queue_.push(pending_task); | 608 incoming_queue_.push(*pending_task); |
| 609 pending_task->task.Reset(); |
| 517 if (!was_empty) | 610 if (!was_empty) |
| 518 return; // Someone else should have started the sub-pump. | 611 return; // Someone else should have started the sub-pump. |
| 519 | 612 |
| 520 pump = pump_; | 613 pump = pump_; |
| 521 } | 614 } |
| 522 // Since the incoming_queue_ may contain a task that destroys this message | 615 // Since the incoming_queue_ may contain a task that destroys this message |
| 523 // loop, we cannot exit incoming_queue_lock_ until we are done with |this|. | 616 // loop, we cannot exit incoming_queue_lock_ until we are done with |this|. |
| 524 // We use a stack-based reference to the message pump so that we can call | 617 // We use a stack-based reference to the message pump so that we can call |
| 525 // ScheduleWork outside of incoming_queue_lock_. | 618 // ScheduleWork outside of incoming_queue_lock_. |
| 526 | 619 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 ReloadWorkQueue(); | 652 ReloadWorkQueue(); |
| 560 if (work_queue_.empty()) | 653 if (work_queue_.empty()) |
| 561 break; | 654 break; |
| 562 | 655 |
| 563 // Execute oldest task. | 656 // Execute oldest task. |
| 564 do { | 657 do { |
| 565 PendingTask pending_task = work_queue_.front(); | 658 PendingTask pending_task = work_queue_.front(); |
| 566 work_queue_.pop(); | 659 work_queue_.pop(); |
| 567 if (!pending_task.delayed_run_time.is_null()) { | 660 if (!pending_task.delayed_run_time.is_null()) { |
| 568 AddToDelayedWorkQueue(pending_task); | 661 AddToDelayedWorkQueue(pending_task); |
| 569 // If we changed the topmost task, then it is time to re-schedule. | 662 // If we changed the topmost task, then it is time to reschedule. |
| 570 if (delayed_work_queue_.top().task == pending_task.task) | 663 if (delayed_work_queue_.top().task.Equals(pending_task.task)) |
| 571 pump_->ScheduleDelayedWork(pending_task.delayed_run_time); | 664 pump_->ScheduleDelayedWork(pending_task.delayed_run_time); |
| 572 } else { | 665 } else { |
| 573 if (DeferOrRunPendingTask(pending_task)) | 666 if (DeferOrRunPendingTask(pending_task)) |
| 574 return true; | 667 return true; |
| 575 } | 668 } |
| 576 } while (!work_queue_.empty()); | 669 } while (!work_queue_.empty()); |
| 577 } | 670 } |
| 578 | 671 |
| 579 // Nothing happened. | 672 // Nothing happened. |
| 580 return false; | 673 return false; |
| 581 } | 674 } |
| 582 | 675 |
| 583 bool MessageLoop::DoDelayedWork(base::TimeTicks* next_delayed_work_time) { | 676 bool MessageLoop::DoDelayedWork(TimeTicks* next_delayed_work_time) { |
| 584 if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) { | 677 if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) { |
| 585 recent_time_ = *next_delayed_work_time = TimeTicks(); | 678 recent_time_ = *next_delayed_work_time = TimeTicks(); |
| 586 return false; | 679 return false; |
| 587 } | 680 } |
| 588 | 681 |
| 589 // When we "fall behind," there will be a lot of tasks in the delayed work | 682 // When we "fall behind," there will be a lot of tasks in the delayed work |
| 590 // queue that are ready to run. To increase efficiency when we fall behind, | 683 // queue that are ready to run. To increase efficiency when we fall behind, |
| 591 // we will only call Time::Now() intermittently, and then process all tasks | 684 // we will only call Time::Now() intermittently, and then process all tasks |
| 592 // that are ready to run before calling it again. As a result, the more we | 685 // that are ready to run before calling it again. As a result, the more we |
| 593 // fall behind (and have a lot of ready-to-run delayed tasks), the more | 686 // fall behind (and have a lot of ready-to-run delayed tasks), the more |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 #endif | 734 #endif |
| 642 } | 735 } |
| 643 | 736 |
| 644 MessageLoop::AutoRunState::~AutoRunState() { | 737 MessageLoop::AutoRunState::~AutoRunState() { |
| 645 loop_->state_ = previous_state_; | 738 loop_->state_ = previous_state_; |
| 646 } | 739 } |
| 647 | 740 |
| 648 //------------------------------------------------------------------------------ | 741 //------------------------------------------------------------------------------ |
| 649 // MessageLoop::PendingTask | 742 // MessageLoop::PendingTask |
| 650 | 743 |
| 744 MessageLoop::PendingTask::PendingTask( |
| 745 const base::Closure& task, |
| 746 const tracked_objects::Location& posted_from, |
| 747 TimeTicks delayed_run_time, |
| 748 bool nestable) |
| 749 : task(task), |
| 750 time_posted(TimeTicks::Now()), |
| 751 delayed_run_time(delayed_run_time), |
| 752 sequence_num(0), |
| 753 nestable(nestable) { |
| 754 #if defined(TRACK_ALL_TASK_OBJECTS) |
| 755 if (tracked_objects::ThreadData::IsActive()) { |
| 756 tracked_objects::ThreadData* current_thread_data = |
| 757 tracked_objects::ThreadData::current(); |
| 758 if (current_thread_data) { |
| 759 post_births = current_thread_data->TallyABirth(posted_from); |
| 760 } else { |
| 761 // Shutdown started, and this thread wasn't registered. |
| 762 post_births = NULL; |
| 763 } |
| 764 } |
| 765 #endif // defined(TRACK_ALL_TASK_OBJECTS) |
| 766 } |
| 767 |
| 651 bool MessageLoop::PendingTask::operator<(const PendingTask& other) const { | 768 bool MessageLoop::PendingTask::operator<(const PendingTask& other) const { |
| 652 // Since the top of a priority queue is defined as the "greatest" element, we | 769 // Since the top of a priority queue is defined as the "greatest" element, we |
| 653 // need to invert the comparison here. We want the smaller time to be at the | 770 // need to invert the comparison here. We want the smaller time to be at the |
| 654 // top of the heap. | 771 // top of the heap. |
| 655 | 772 |
| 656 if (delayed_run_time < other.delayed_run_time) | 773 if (delayed_run_time < other.delayed_run_time) |
| 657 return false; | 774 return false; |
| 658 | 775 |
| 659 if (delayed_run_time > other.delayed_run_time) | 776 if (delayed_run_time > other.delayed_run_time) |
| 660 return true; | 777 return true; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 Watcher *delegate) { | 834 Watcher *delegate) { |
| 718 return pump_libevent()->WatchFileDescriptor( | 835 return pump_libevent()->WatchFileDescriptor( |
| 719 fd, | 836 fd, |
| 720 persistent, | 837 persistent, |
| 721 static_cast<base::MessagePumpLibevent::Mode>(mode), | 838 static_cast<base::MessagePumpLibevent::Mode>(mode), |
| 722 controller, | 839 controller, |
| 723 delegate); | 840 delegate); |
| 724 } | 841 } |
| 725 | 842 |
| 726 #endif | 843 #endif |
| OLD | NEW |