Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 } | 204 } |
| 205 | 205 |
| 206 void MessageLoop::RemoveDestructionObserver( | 206 void MessageLoop::RemoveDestructionObserver( |
| 207 DestructionObserver* destruction_observer) { | 207 DestructionObserver* destruction_observer) { |
| 208 DCHECK_EQ(this, current()); | 208 DCHECK_EQ(this, current()); |
| 209 destruction_observers_.RemoveObserver(destruction_observer); | 209 destruction_observers_.RemoveObserver(destruction_observer); |
| 210 } | 210 } |
| 211 | 211 |
| 212 void MessageLoop::PostTask( | 212 void MessageLoop::PostTask( |
| 213 const tracked_objects::Location& from_here, Task* task) { | 213 const tracked_objects::Location& from_here, Task* task) { |
| 214 PostTask_Helper(from_here, task, 0, true); | 214 task->SetBirthPlace(from_here); |
| 215 PendingTask pending_task(task, CalculateDelayedRuntime(0), true); | |
| 216 AddToIncomingQueue(pending_task); | |
| 215 } | 217 } |
| 216 | 218 |
| 217 void MessageLoop::PostDelayedTask( | 219 void MessageLoop::PostDelayedTask( |
| 218 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { | 220 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { |
| 219 PostTask_Helper(from_here, task, delay_ms, true); | 221 task->SetBirthPlace(from_here); |
| 222 PendingTask pending_task(task, CalculateDelayedRuntime(delay_ms), true); | |
| 223 AddToIncomingQueue(pending_task); | |
| 220 } | 224 } |
| 221 | 225 |
| 222 void MessageLoop::PostNonNestableTask( | 226 void MessageLoop::PostNonNestableTask( |
| 223 const tracked_objects::Location& from_here, Task* task) { | 227 const tracked_objects::Location& from_here, Task* task) { |
| 224 PostTask_Helper(from_here, task, 0, false); | 228 task->SetBirthPlace(from_here); |
| 229 PendingTask pending_task(task, CalculateDelayedRuntime(0), false); | |
| 230 AddToIncomingQueue(pending_task); | |
| 225 } | 231 } |
| 226 | 232 |
| 227 void MessageLoop::PostNonNestableDelayedTask( | 233 void MessageLoop::PostNonNestableDelayedTask( |
| 228 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { | 234 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { |
| 229 PostTask_Helper(from_here, task, delay_ms, false); | 235 task->SetBirthPlace(from_here); |
| 236 PendingTask pending_task(task, CalculateDelayedRuntime(delay_ms), false); | |
| 237 AddToIncomingQueue(pending_task); | |
| 238 } | |
| 239 | |
| 240 void MessageLoop::PostClosure( | |
| 241 const tracked_objects::Location& from_here, const base::Closure& closure) { | |
| 242 // TODO(ajwong): Record |from_here| correctly for Closures. | |
|
willchan no longer on Chromium
2011/02/09 05:51:48
IIRC, when we discussed this before, I suggested r
| |
| 243 PendingTask pending_task(closure, CalculateDelayedRuntime(0), true); | |
| 244 AddToIncomingQueue(pending_task); | |
| 245 } | |
| 246 | |
| 247 void MessageLoop::PostDelayedClosure( | |
| 248 const tracked_objects::Location& from_here, const base::Closure& closure, | |
| 249 int64 delay_ms) { | |
| 250 // TODO(ajwong): Record |from_here| correctly for Closures. | |
| 251 PendingTask pending_task(closure, CalculateDelayedRuntime(delay_ms), true); | |
| 252 AddToIncomingQueue(pending_task); | |
| 253 } | |
| 254 | |
| 255 void MessageLoop::PostNonNestableClosure( | |
| 256 const tracked_objects::Location& from_here, const base::Closure& closure) { | |
| 257 // TODO(ajwong): Record |from_here| correctly for Closures. | |
| 258 PendingTask pending_task(closure, CalculateDelayedRuntime(0), false); | |
| 259 AddToIncomingQueue(pending_task); | |
| 260 } | |
| 261 | |
| 262 void MessageLoop::PostNonNestableDelayedClosure( | |
| 263 const tracked_objects::Location& from_here, const base::Closure& closure, | |
| 264 int64 delay_ms) { | |
| 265 // TODO(ajwong): Record |from_here| correctly for Closures. | |
| 266 PendingTask pending_task(closure, CalculateDelayedRuntime(delay_ms), false); | |
| 267 AddToIncomingQueue(pending_task); | |
| 230 } | 268 } |
| 231 | 269 |
| 232 void MessageLoop::Run() { | 270 void MessageLoop::Run() { |
| 233 AutoRunState save_state(this); | 271 AutoRunState save_state(this); |
| 234 RunHandler(); | 272 RunHandler(); |
| 235 } | 273 } |
| 236 | 274 |
| 237 void MessageLoop::RunAllPending() { | 275 void MessageLoop::RunAllPending() { |
| 238 AutoRunState save_state(this); | 276 AutoRunState save_state(this); |
| 239 state_->quit_received = true; // Means run until we would otherwise block. | 277 state_->quit_received = true; // Means run until we would otherwise block. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 338 } | 376 } |
| 339 | 377 |
| 340 bool MessageLoop::ProcessNextDelayedNonNestableTask() { | 378 bool MessageLoop::ProcessNextDelayedNonNestableTask() { |
| 341 if (state_->run_depth != 1) | 379 if (state_->run_depth != 1) |
| 342 return false; | 380 return false; |
| 343 | 381 |
| 344 if (deferred_non_nestable_work_queue_.empty()) | 382 if (deferred_non_nestable_work_queue_.empty()) |
| 345 return false; | 383 return false; |
| 346 | 384 |
| 347 Task* task = deferred_non_nestable_work_queue_.front().task; | 385 Task* task = deferred_non_nestable_work_queue_.front().task; |
| 348 deferred_non_nestable_work_queue_.pop(); | 386 if (task) { |
| 349 | 387 deferred_non_nestable_work_queue_.pop(); |
| 350 RunTask(task); | 388 RunTask(task); |
| 389 } else { | |
| 390 // Take a copy since we will pop the queue. | |
| 391 base::Closure closure = deferred_non_nestable_work_queue_.front().closure; | |
| 392 deferred_non_nestable_work_queue_.pop(); | |
| 393 RunClosure(closure); | |
| 394 } | |
| 351 return true; | 395 return true; |
| 352 } | 396 } |
| 353 | 397 |
| 354 void MessageLoop::RunTask(Task* task) { | 398 void MessageLoop::RunTask(Task* task) { |
| 355 DCHECK(nestable_tasks_allowed_); | 399 DCHECK(nestable_tasks_allowed_); |
| 356 // Execute the task and assume the worst: It is probably not reentrant. | 400 // Execute the task and assume the worst: It is probably not reentrant. |
| 357 nestable_tasks_allowed_ = false; | 401 nestable_tasks_allowed_ = false; |
| 358 | 402 |
| 359 HistogramEvent(kTaskRunEvent); | 403 HistogramEvent(kTaskRunEvent); |
| 360 FOR_EACH_OBSERVER(TaskObserver, task_observers_, | 404 FOR_EACH_OBSERVER(TaskObserver, task_observers_, |
| 361 WillProcessTask(task)); | 405 WillProcessTask(task)); |
| 362 task->Run(); | 406 task->Run(); |
| 363 FOR_EACH_OBSERVER(TaskObserver, task_observers_, DidProcessTask(task)); | 407 FOR_EACH_OBSERVER(TaskObserver, task_observers_, DidProcessTask(task)); |
| 364 delete task; | 408 delete task; |
| 365 | 409 |
| 366 nestable_tasks_allowed_ = true; | 410 nestable_tasks_allowed_ = true; |
| 367 } | 411 } |
| 368 | 412 |
| 413 void MessageLoop::RunClosure(const base::Closure& closure) { | |
| 414 DCHECK(nestable_tasks_allowed_); | |
| 415 // Execute the task and assume the worst: It is probably not reentrant. | |
| 416 nestable_tasks_allowed_ = false; | |
| 417 | |
| 418 // TODO(ajwong): Figure out how to handle FOR_EACH_OBSERVER. | |
| 419 closure.Run(); | |
| 420 | |
| 421 nestable_tasks_allowed_ = true; | |
| 422 } | |
| 423 | |
| 369 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { | 424 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { |
| 370 if (pending_task.nestable || state_->run_depth == 1) { | 425 if (pending_task.nestable || state_->run_depth == 1) { |
| 371 RunTask(pending_task.task); | 426 if (pending_task.task) { |
| 372 // Show that we ran a task (Note: a new one might arrive as a | 427 RunTask(pending_task.task); |
| 373 // consequence!). | 428 // Show that we ran a task (Note: a new one might arrive as a |
| 429 // consequence!). | |
| 430 } else { | |
| 431 RunClosure(pending_task.closure); | |
| 432 } | |
| 374 return true; | 433 return true; |
| 375 } | 434 } |
| 376 | 435 |
| 377 // We couldn't run the task now because we're in a nested message loop | 436 // We couldn't run the task now because we're in a nested message loop |
| 378 // and the task isn't nestable. | 437 // and the task isn't nestable. |
| 379 deferred_non_nestable_work_queue_.push(pending_task); | 438 deferred_non_nestable_work_queue_.push(pending_task); |
| 380 return false; | 439 return false; |
| 381 } | 440 } |
| 382 | 441 |
| 383 void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) { | 442 void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 447 } | 506 } |
| 448 did_work |= !delayed_work_queue_.empty(); | 507 did_work |= !delayed_work_queue_.empty(); |
| 449 while (!delayed_work_queue_.empty()) { | 508 while (!delayed_work_queue_.empty()) { |
| 450 Task* task = delayed_work_queue_.top().task; | 509 Task* task = delayed_work_queue_.top().task; |
| 451 delayed_work_queue_.pop(); | 510 delayed_work_queue_.pop(); |
| 452 delete task; | 511 delete task; |
| 453 } | 512 } |
| 454 return did_work; | 513 return did_work; |
| 455 } | 514 } |
| 456 | 515 |
| 457 // Possibly called on a background thread! | 516 base::TimeTicks MessageLoop::CalculateDelayedRuntime(int64 delay_ms) { |
| 458 void MessageLoop::PostTask_Helper( | 517 base::TimeTicks delayed_run_time; |
| 459 const tracked_objects::Location& from_here, Task* task, int64 delay_ms, | |
| 460 bool nestable) { | |
| 461 task->SetBirthPlace(from_here); | |
| 462 | |
| 463 PendingTask pending_task(task, nestable); | |
| 464 | |
| 465 if (delay_ms > 0) { | 518 if (delay_ms > 0) { |
| 466 pending_task.delayed_run_time = | 519 delayed_run_time = |
| 467 TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms); | 520 TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms); |
| 468 | 521 |
| 469 #if defined(OS_WIN) | 522 #if defined(OS_WIN) |
| 470 if (high_resolution_timer_expiration_.is_null()) { | 523 if (high_resolution_timer_expiration_.is_null()) { |
| 471 // Windows timers are granular to 15.6ms. If we only set high-res | 524 // Windows timers are granular to 15.6ms. If we only set high-res |
| 472 // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms, | 525 // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms, |
| 473 // which as a percentage is pretty inaccurate. So enable high | 526 // which as a percentage is pretty inaccurate. So enable high |
| 474 // res timers for any timer which is within 2x of the granularity. | 527 // res timers for any timer which is within 2x of the granularity. |
| 475 // This is a tradeoff between accuracy and power management. | 528 // This is a tradeoff between accuracy and power management. |
| 476 bool needs_high_res_timers = | 529 bool needs_high_res_timers = |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 488 | 541 |
| 489 #if defined(OS_WIN) | 542 #if defined(OS_WIN) |
| 490 if (!high_resolution_timer_expiration_.is_null()) { | 543 if (!high_resolution_timer_expiration_.is_null()) { |
| 491 if (TimeTicks::Now() > high_resolution_timer_expiration_) { | 544 if (TimeTicks::Now() > high_resolution_timer_expiration_) { |
| 492 base::Time::ActivateHighResolutionTimer(false); | 545 base::Time::ActivateHighResolutionTimer(false); |
| 493 high_resolution_timer_expiration_ = TimeTicks(); | 546 high_resolution_timer_expiration_ = TimeTicks(); |
| 494 } | 547 } |
| 495 } | 548 } |
| 496 #endif | 549 #endif |
| 497 | 550 |
| 551 return delayed_run_time; | |
| 552 } | |
| 553 | |
| 554 // Possibly called on a background thread! | |
| 555 void MessageLoop::AddToIncomingQueue(const PendingTask& pending_task) { | |
| 498 // Warning: Don't try to short-circuit, and handle this thread's tasks more | 556 // Warning: Don't try to short-circuit, and handle this thread's tasks more |
| 499 // directly, as it could starve handling of foreign threads. Put every task | 557 // directly, as it could starve handling of foreign threads. Put every task |
| 500 // into this queue. | 558 // into this queue. |
| 501 | 559 |
| 502 scoped_refptr<base::MessagePump> pump; | 560 scoped_refptr<base::MessagePump> pump; |
| 503 { | 561 { |
| 504 base::AutoLock locked(incoming_queue_lock_); | 562 base::AutoLock locked(incoming_queue_lock_); |
| 505 | 563 |
| 506 bool was_empty = incoming_queue_.empty(); | 564 bool was_empty = incoming_queue_.empty(); |
| 507 incoming_queue_.push(pending_task); | 565 incoming_queue_.push(pending_task); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 551 if (work_queue_.empty()) | 609 if (work_queue_.empty()) |
| 552 break; | 610 break; |
| 553 | 611 |
| 554 // Execute oldest task. | 612 // Execute oldest task. |
| 555 do { | 613 do { |
| 556 PendingTask pending_task = work_queue_.front(); | 614 PendingTask pending_task = work_queue_.front(); |
| 557 work_queue_.pop(); | 615 work_queue_.pop(); |
| 558 if (!pending_task.delayed_run_time.is_null()) { | 616 if (!pending_task.delayed_run_time.is_null()) { |
| 559 AddToDelayedWorkQueue(pending_task); | 617 AddToDelayedWorkQueue(pending_task); |
| 560 // If we changed the topmost task, then it is time to re-schedule. | 618 // If we changed the topmost task, then it is time to re-schedule. |
| 561 if (delayed_work_queue_.top().task == pending_task.task) | 619 if ((delayed_work_queue_.top().task == pending_task.task)) { |
| 562 pump_->ScheduleDelayedWork(pending_task.delayed_run_time); | 620 pump_->ScheduleDelayedWork(pending_task.delayed_run_time); |
| 621 } | |
| 563 } else { | 622 } else { |
| 564 if (DeferOrRunPendingTask(pending_task)) | 623 if (DeferOrRunPendingTask(pending_task)) |
| 565 return true; | 624 return true; |
| 566 } | 625 } |
| 567 } while (!work_queue_.empty()); | 626 } while (!work_queue_.empty()); |
| 568 } | 627 } |
| 569 | 628 |
| 570 // Nothing happened. | 629 // Nothing happened. |
| 571 return false; | 630 return false; |
| 572 } | 631 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 702 Watcher *delegate) { | 761 Watcher *delegate) { |
| 703 return pump_libevent()->WatchFileDescriptor( | 762 return pump_libevent()->WatchFileDescriptor( |
| 704 fd, | 763 fd, |
| 705 persistent, | 764 persistent, |
| 706 static_cast<base::MessagePumpLibevent::Mode>(mode), | 765 static_cast<base::MessagePumpLibevent::Mode>(mode), |
| 707 controller, | 766 controller, |
| 708 delegate); | 767 delegate); |
| 709 } | 768 } |
| 710 | 769 |
| 711 #endif | 770 #endif |
| OLD | NEW |