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( | |
willchan no longer on Chromium
2011/02/15 01:41:11
For all these Post*Closure() functions, you need t
| |
241 const tracked_objects::Location& from_here, const base::Closure& closure) { | |
242 // TODO(ajwong): Record |from_here| correctly for Closures. | |
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 HistogramEvent(kTaskRunEvent); | |
419 // TODO(ajwong): Figure out how to handle FOR_EACH_OBSERVER. | |
willchan no longer on Chromium
2011/02/15 01:41:11
Probably should add a ClosureObserver.
awong
2011/02/15 08:24:42
Sounds like maybe we should modify the observer to
| |
420 closure.Run(); | |
421 | |
422 nestable_tasks_allowed_ = true; | |
423 } | |
424 | |
369 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { | 425 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { |
370 if (pending_task.nestable || state_->run_depth == 1) { | 426 if (pending_task.nestable || state_->run_depth == 1) { |
371 RunTask(pending_task.task); | 427 if (pending_task.task) { |
372 // Show that we ran a task (Note: a new one might arrive as a | 428 RunTask(pending_task.task); |
373 // consequence!). | 429 // Show that we ran a task (Note: a new one might arrive as a |
430 // consequence!). | |
431 } else { | |
432 RunClosure(pending_task.closure); | |
433 } | |
374 return true; | 434 return true; |
375 } | 435 } |
376 | 436 |
377 // We couldn't run the task now because we're in a nested message loop | 437 // We couldn't run the task now because we're in a nested message loop |
378 // and the task isn't nestable. | 438 // and the task isn't nestable. |
379 deferred_non_nestable_work_queue_.push(pending_task); | 439 deferred_non_nestable_work_queue_.push(pending_task); |
380 return false; | 440 return false; |
381 } | 441 } |
382 | 442 |
383 void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) { | 443 void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 } | 507 } |
448 did_work |= !delayed_work_queue_.empty(); | 508 did_work |= !delayed_work_queue_.empty(); |
449 while (!delayed_work_queue_.empty()) { | 509 while (!delayed_work_queue_.empty()) { |
450 Task* task = delayed_work_queue_.top().task; | 510 Task* task = delayed_work_queue_.top().task; |
451 delayed_work_queue_.pop(); | 511 delayed_work_queue_.pop(); |
452 delete task; | 512 delete task; |
453 } | 513 } |
454 return did_work; | 514 return did_work; |
455 } | 515 } |
456 | 516 |
457 // Possibly called on a background thread! | 517 base::TimeTicks MessageLoop::CalculateDelayedRuntime(int64 delay_ms) { |
458 void MessageLoop::PostTask_Helper( | 518 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) { | 519 if (delay_ms > 0) { |
466 pending_task.delayed_run_time = | 520 delayed_run_time = |
467 TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms); | 521 TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms); |
468 | 522 |
469 #if defined(OS_WIN) | 523 #if defined(OS_WIN) |
470 if (high_resolution_timer_expiration_.is_null()) { | 524 if (high_resolution_timer_expiration_.is_null()) { |
471 // Windows timers are granular to 15.6ms. If we only set high-res | 525 // 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, | 526 // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms, |
473 // which as a percentage is pretty inaccurate. So enable high | 527 // which as a percentage is pretty inaccurate. So enable high |
474 // res timers for any timer which is within 2x of the granularity. | 528 // res timers for any timer which is within 2x of the granularity. |
475 // This is a tradeoff between accuracy and power management. | 529 // This is a tradeoff between accuracy and power management. |
476 bool needs_high_res_timers = | 530 bool needs_high_res_timers = |
(...skipping 11 matching lines...) Expand all Loading... | |
488 | 542 |
489 #if defined(OS_WIN) | 543 #if defined(OS_WIN) |
490 if (!high_resolution_timer_expiration_.is_null()) { | 544 if (!high_resolution_timer_expiration_.is_null()) { |
491 if (TimeTicks::Now() > high_resolution_timer_expiration_) { | 545 if (TimeTicks::Now() > high_resolution_timer_expiration_) { |
492 base::Time::ActivateHighResolutionTimer(false); | 546 base::Time::ActivateHighResolutionTimer(false); |
493 high_resolution_timer_expiration_ = TimeTicks(); | 547 high_resolution_timer_expiration_ = TimeTicks(); |
494 } | 548 } |
495 } | 549 } |
496 #endif | 550 #endif |
497 | 551 |
552 return delayed_run_time; | |
553 } | |
554 | |
555 // Possibly called on a background thread! | |
556 void MessageLoop::AddToIncomingQueue(const PendingTask& pending_task) { | |
willchan no longer on Chromium
2011/02/15 01:41:11
You should sanity check PendingTask here. task XOR
awong
2011/02/15 08:24:42
Sounds like Darin is in for cowboying it up and ju
| |
498 // Warning: Don't try to short-circuit, and handle this thread's tasks more | 557 // 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 | 558 // directly, as it could starve handling of foreign threads. Put every task |
500 // into this queue. | 559 // into this queue. |
501 | 560 |
502 scoped_refptr<base::MessagePump> pump; | 561 scoped_refptr<base::MessagePump> pump; |
503 { | 562 { |
504 base::AutoLock locked(incoming_queue_lock_); | 563 base::AutoLock locked(incoming_queue_lock_); |
505 | 564 |
506 bool was_empty = incoming_queue_.empty(); | 565 bool was_empty = incoming_queue_.empty(); |
507 incoming_queue_.push(pending_task); | 566 incoming_queue_.push(pending_task); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
551 if (work_queue_.empty()) | 610 if (work_queue_.empty()) |
552 break; | 611 break; |
553 | 612 |
554 // Execute oldest task. | 613 // Execute oldest task. |
555 do { | 614 do { |
556 PendingTask pending_task = work_queue_.front(); | 615 PendingTask pending_task = work_queue_.front(); |
557 work_queue_.pop(); | 616 work_queue_.pop(); |
558 if (!pending_task.delayed_run_time.is_null()) { | 617 if (!pending_task.delayed_run_time.is_null()) { |
559 AddToDelayedWorkQueue(pending_task); | 618 AddToDelayedWorkQueue(pending_task); |
560 // If we changed the topmost task, then it is time to re-schedule. | 619 // If we changed the topmost task, then it is time to re-schedule. |
561 if (delayed_work_queue_.top().task == pending_task.task) | 620 // |
621 // TODO(ajwong): I don't understand this conditional. It will call | |
622 // ScheduleDelayedWork() too often for Closure since task == NULL. | |
623 // It seems like we should be checking sequence numbers instead. | |
624 if (delayed_work_queue_.top().task == pending_task.task) { | |
562 pump_->ScheduleDelayedWork(pending_task.delayed_run_time); | 625 pump_->ScheduleDelayedWork(pending_task.delayed_run_time); |
626 } | |
563 } else { | 627 } else { |
564 if (DeferOrRunPendingTask(pending_task)) | 628 if (DeferOrRunPendingTask(pending_task)) |
565 return true; | 629 return true; |
566 } | 630 } |
567 } while (!work_queue_.empty()); | 631 } while (!work_queue_.empty()); |
568 } | 632 } |
569 | 633 |
570 // Nothing happened. | 634 // Nothing happened. |
571 return false; | 635 return false; |
572 } | 636 } |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
702 Watcher *delegate) { | 766 Watcher *delegate) { |
703 return pump_libevent()->WatchFileDescriptor( | 767 return pump_libevent()->WatchFileDescriptor( |
704 fd, | 768 fd, |
705 persistent, | 769 persistent, |
706 static_cast<base::MessagePumpLibevent::Mode>(mode), | 770 static_cast<base::MessagePumpLibevent::Mode>(mode), |
707 controller, | 771 controller, |
708 delegate); | 772 delegate); |
709 } | 773 } |
710 | 774 |
711 #endif | 775 #endif |
OLD | NEW |