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

Side by Side Diff: base/message_loop.cc

Issue 6463013: Add support for base::Closure in the MessageLoop. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/base
Patch Set: work around __stdcall Created 9 years, 10 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
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698