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

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: address will's comments. Created 9 years, 9 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
« no previous file with comments | « base/message_loop.h ('k') | base/message_loop_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 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
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 a Owned() tag that behaves like a
85 // "Unique" pointer. If we had that, and Tasks were always safe to delete on
86 // 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::DeletePendingClosures() 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);
94 return EXCEPTION_CONTINUE_SEARCH; 128 return EXCEPTION_CONTINUE_SEARCH;
95 } 129 }
96 130
97 // Retrieves a pointer to the current unhandled exception filter. There 131 // Retrieves a pointer to the current unhandled exception filter. There
98 // is no standalone getter method. 132 // is no standalone getter method.
99 static LPTOP_LEVEL_EXCEPTION_FILTER GetTopSEHFilter() { 133 static LPTOP_LEVEL_EXCEPTION_FILTER GetTopSEHFilter() {
100 LPTOP_LEVEL_EXCEPTION_FILTER top_filter = NULL; 134 LPTOP_LEVEL_EXCEPTION_FILTER top_filter = NULL;
101 top_filter = ::SetUnhandledExceptionFilter(0); 135 top_filter = ::SetUnhandledExceptionFilter(0);
102 ::SetUnhandledExceptionFilter(top_filter); 136 ::SetUnhandledExceptionFilter(top_filter);
103 return top_filter; 137 return top_filter;
104 } 138 }
105 139
106 #endif // defined(OS_WIN) 140 #endif // defined(OS_WIN)
107 141
108 //------------------------------------------------------------------------------ 142 //------------------------------------------------------------------------------
109 143
110 MessageLoop::TaskObserver::TaskObserver() { 144 MessageLoop::ClosureObserver::ClosureObserver() {
111 } 145 }
112 146
113 MessageLoop::TaskObserver::~TaskObserver() { 147 MessageLoop::ClosureObserver::~ClosureObserver() {
114 } 148 }
115 149
116 MessageLoop::DestructionObserver::~DestructionObserver() { 150 MessageLoop::DestructionObserver::~DestructionObserver() {
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 state_(NULL), 159 state_(NULL),
160 should_leak_tasks_(true),
126 next_sequence_num_(0) { 161 next_sequence_num_(0) {
127 DCHECK(!current()) << "should only have one message loop per thread"; 162 DCHECK(!current()) << "should only have one message loop per thread";
128 lazy_tls_ptr.Pointer()->Set(this); 163 lazy_tls_ptr.Pointer()->Set(this);
129 164
130 // TODO(rvargas): Get rid of the OS guards. 165 // TODO(rvargas): Get rid of the OS guards.
131 #if defined(OS_WIN) 166 #if defined(OS_WIN)
132 #define MESSAGE_PUMP_UI new base::MessagePumpForUI() 167 #define MESSAGE_PUMP_UI new base::MessagePumpForUI()
133 #define MESSAGE_PUMP_IO new base::MessagePumpForIO() 168 #define MESSAGE_PUMP_IO new base::MessagePumpForIO()
134 #elif defined(OS_MACOSX) 169 #elif defined(OS_MACOSX)
135 #define MESSAGE_PUMP_UI base::MessagePumpMac::Create() 170 #define MESSAGE_PUMP_UI base::MessagePumpMac::Create()
(...skipping 29 matching lines...) Expand all
165 DCHECK(!state_); 200 DCHECK(!state_);
166 201
167 // Clean up any unprocessed tasks, but take care: deleting a task could 202 // Clean up any unprocessed tasks, but take care: deleting a task could
168 // result in the addition of more tasks (e.g., via DeleteSoon). We set a 203 // result in the addition of more tasks (e.g., via DeleteSoon). We set a
169 // limit on the number of times we will allow a deleted task to generate more 204 // limit on the number of times we will allow a deleted task to generate more
170 // tasks. Normally, we should only pass through this loop once or twice. If 205 // tasks. Normally, we should only pass through this loop once or twice. If
171 // we end up hitting the loop limit, then it is probably due to one task that 206 // we end up hitting the loop limit, then it is probably due to one task that
172 // is being stubborn. Inspect the queues to see who is left. 207 // is being stubborn. Inspect the queues to see who is left.
173 bool did_work; 208 bool did_work;
174 for (int i = 0; i < 100; ++i) { 209 for (int i = 0; i < 100; ++i) {
175 DeletePendingTasks(); 210 DeletePendingClosures();
176 ReloadWorkQueue(); 211 ReloadWorkQueue();
177 // If we end up with empty queues, then break out of the loop. 212 // If we end up with empty queues, then break out of the loop.
178 did_work = DeletePendingTasks(); 213 did_work = DeletePendingClosures();
179 if (!did_work) 214 if (!did_work)
180 break; 215 break;
181 } 216 }
182 DCHECK(!did_work); 217 DCHECK(!did_work);
183 218
184 // Let interested parties have one last shot at accessing this. 219 // Let interested parties have one last shot at accessing this.
185 FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_, 220 FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_,
186 WillDestroyCurrentMessageLoop()); 221 WillDestroyCurrentMessageLoop());
187 222
188 // OK, now make it so that no one can find us. 223 // OK, now make it so that no one can find us.
(...skipping 20 matching lines...) Expand all
209 } 244 }
210 245
211 void MessageLoop::RemoveDestructionObserver( 246 void MessageLoop::RemoveDestructionObserver(
212 DestructionObserver* destruction_observer) { 247 DestructionObserver* destruction_observer) {
213 DCHECK_EQ(this, current()); 248 DCHECK_EQ(this, current());
214 destruction_observers_.RemoveObserver(destruction_observer); 249 destruction_observers_.RemoveObserver(destruction_observer);
215 } 250 }
216 251
217 void MessageLoop::PostTask( 252 void MessageLoop::PostTask(
218 const tracked_objects::Location& from_here, Task* task) { 253 const tracked_objects::Location& from_here, Task* task) {
219 PostTask_Helper(from_here, task, 0, true); 254 PendingClosure pending_closure(
255 base::Bind(&TaskClosureAdapter::Run,
256 new TaskClosureAdapter(task, &should_leak_tasks_)),
257 from_here,
258 CalculateDelayedRuntime(0), true);
259 // TODO(ajwong): This failed because pending_closure outlives the add to the
260 // incoming_queue_.
261 AddToIncomingQueue(&pending_closure);
220 } 262 }
221 263
222 void MessageLoop::PostDelayedTask( 264 void MessageLoop::PostDelayedTask(
223 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { 265 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
224 PostTask_Helper(from_here, task, delay_ms, true); 266 PendingClosure pending_closure(
267 base::Bind(&TaskClosureAdapter::Run,
268 new TaskClosureAdapter(task, &should_leak_tasks_)),
269 from_here,
270 CalculateDelayedRuntime(delay_ms), true);
271 AddToIncomingQueue(&pending_closure);
225 } 272 }
226 273
227 void MessageLoop::PostNonNestableTask( 274 void MessageLoop::PostNonNestableTask(
228 const tracked_objects::Location& from_here, Task* task) { 275 const tracked_objects::Location& from_here, Task* task) {
229 PostTask_Helper(from_here, task, 0, false); 276 PendingClosure pending_closure(
277 base::Bind(&TaskClosureAdapter::Run,
278 new TaskClosureAdapter(task, &should_leak_tasks_)),
279 from_here,
280 CalculateDelayedRuntime(0), false);
281 AddToIncomingQueue(&pending_closure);
230 } 282 }
231 283
232 void MessageLoop::PostNonNestableDelayedTask( 284 void MessageLoop::PostNonNestableDelayedTask(
233 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { 285 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
234 PostTask_Helper(from_here, task, delay_ms, false); 286 PendingClosure pending_closure(
287 base::Bind(&TaskClosureAdapter::Run,
288 new TaskClosureAdapter(task, &should_leak_tasks_)),
289 from_here,
290 CalculateDelayedRuntime(delay_ms), false);
291 AddToIncomingQueue(&pending_closure);
292 }
293
294 void MessageLoop::PostClosure(
295 const tracked_objects::Location& from_here, const base::Closure& closure) {
296 DCHECK(!closure.is_null());
297 PendingClosure pending_closure(closure, from_here,
298 CalculateDelayedRuntime(0), true);
299 AddToIncomingQueue(&pending_closure);
300 }
301
302 void MessageLoop::PostDelayedClosure(
303 const tracked_objects::Location& from_here, const base::Closure& closure,
304 int64 delay_ms) {
305 DCHECK(!closure.is_null());
306 PendingClosure pending_closure(closure, from_here,
307 CalculateDelayedRuntime(delay_ms), true);
308 AddToIncomingQueue(&pending_closure);
309 }
310
311 void MessageLoop::PostNonNestableClosure(
312 const tracked_objects::Location& from_here, const base::Closure& closure) {
313 DCHECK(!closure.is_null());
314 PendingClosure pending_closure(closure, from_here,
315 CalculateDelayedRuntime(0), false);
316 AddToIncomingQueue(&pending_closure);
317 }
318
319 void MessageLoop::PostNonNestableDelayedClosure(
320 const tracked_objects::Location& from_here, const base::Closure& closure,
321 int64 delay_ms) {
322 DCHECK(!closure.is_null());
323 PendingClosure pending_closure(closure, from_here,
324 CalculateDelayedRuntime(delay_ms), false);
325 AddToIncomingQueue(&pending_closure);
235 } 326 }
236 327
237 void MessageLoop::Run() { 328 void MessageLoop::Run() {
238 AutoRunState save_state(this); 329 AutoRunState save_state(this);
239 RunHandler(); 330 RunHandler();
240 } 331 }
241 332
242 void MessageLoop::RunAllPending() { 333 void MessageLoop::RunAllPending() {
243 AutoRunState save_state(this); 334 AutoRunState save_state(this);
244 state_->quit_received = true; // Means run until we would otherwise block. 335 state_->quit_received = true; // Means run until we would otherwise block.
(...skipping 29 matching lines...) Expand all
274 } 365 }
275 366
276 bool MessageLoop::NestableTasksAllowed() const { 367 bool MessageLoop::NestableTasksAllowed() const {
277 return nestable_tasks_allowed_; 368 return nestable_tasks_allowed_;
278 } 369 }
279 370
280 bool MessageLoop::IsNested() { 371 bool MessageLoop::IsNested() {
281 return state_->run_depth > 1; 372 return state_->run_depth > 1;
282 } 373 }
283 374
284 void MessageLoop::AddTaskObserver(TaskObserver* task_observer) { 375 void MessageLoop::AddClosureObserver(ClosureObserver* closure_observer) {
285 DCHECK_EQ(this, current()); 376 DCHECK_EQ(this, current());
286 task_observers_.AddObserver(task_observer); 377 closure_observers_.AddObserver(closure_observer);
287 } 378 }
288 379
289 void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) { 380 void MessageLoop::RemoveClosureObserver(ClosureObserver* closure_observer) {
290 DCHECK_EQ(this, current()); 381 DCHECK_EQ(this, current());
291 task_observers_.RemoveObserver(task_observer); 382 closure_observers_.RemoveObserver(closure_observer);
292 } 383 }
293 384
294 void MessageLoop::AssertIdle() const { 385 void MessageLoop::AssertIdle() const {
295 // We only check |incoming_queue_|, since we don't want to lock |work_queue_|. 386 // We only check |incoming_queue_|, since we don't want to lock |work_queue_|.
296 base::AutoLock lock(incoming_queue_lock_); 387 base::AutoLock lock(incoming_queue_lock_);
297 DCHECK(incoming_queue_.empty()); 388 DCHECK(incoming_queue_.empty());
298 } 389 }
299 390
300 //------------------------------------------------------------------------------ 391 //------------------------------------------------------------------------------
301 392
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 pump_->Run(this); 433 pump_->Run(this);
343 } 434 }
344 435
345 bool MessageLoop::ProcessNextDelayedNonNestableTask() { 436 bool MessageLoop::ProcessNextDelayedNonNestableTask() {
346 if (state_->run_depth != 1) 437 if (state_->run_depth != 1)
347 return false; 438 return false;
348 439
349 if (deferred_non_nestable_work_queue_.empty()) 440 if (deferred_non_nestable_work_queue_.empty())
350 return false; 441 return false;
351 442
352 Task* task = deferred_non_nestable_work_queue_.front().task; 443 PendingClosure pending_closure = deferred_non_nestable_work_queue_.front();
353 deferred_non_nestable_work_queue_.pop(); 444 deferred_non_nestable_work_queue_.pop();
354 445
355 RunTask(task); 446 RunClosure(pending_closure);
356 return true; 447 return true;
357 } 448 }
358 449
359 void MessageLoop::RunTask(Task* task) { 450 void MessageLoop::RunClosure(const PendingClosure& pending_closure) {
360 DCHECK(nestable_tasks_allowed_); 451 DCHECK(nestable_tasks_allowed_);
361 // 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.
362 nestable_tasks_allowed_ = false; 453 nestable_tasks_allowed_ = false;
363 454
364 HistogramEvent(kTaskRunEvent); 455 HistogramEvent(kTaskRunEvent);
365 FOR_EACH_OBSERVER(TaskObserver, task_observers_, 456 FOR_EACH_OBSERVER(ClosureObserver, closure_observers_,
366 WillProcessTask(task)); 457 WillProcessClosure(pending_closure.time_posted));
367 task->Run(); 458 pending_closure.closure.Run();
368 FOR_EACH_OBSERVER(TaskObserver, task_observers_, DidProcessTask(task)); 459 FOR_EACH_OBSERVER(ClosureObserver, closure_observers_,
369 delete task; 460 DidProcessClosure(pending_closure.time_posted));
461
462 #if defined(TRACK_ALL_TASK_OBJECTS)
463 if (tracked_objects::ThreadData::IsActive() && pending_closure.post_births) {
464 tracked_objects::ThreadData::current()->TallyADeath(
465 *pending_closure.post_births,
466 TimeTicks::Now() - pending_closure.time_posted);
467 }
468 #endif // defined(TRACK_ALL_TASK_OBJECTS)
370 469
371 nestable_tasks_allowed_ = true; 470 nestable_tasks_allowed_ = true;
372 } 471 }
373 472
374 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { 473 bool MessageLoop::DeferOrRunPendingClosure(
375 if (pending_task.nestable || state_->run_depth == 1) { 474 const PendingClosure& pending_closure) {
376 RunTask(pending_task.task); 475 if (pending_closure.nestable || state_->run_depth == 1) {
476 RunClosure(pending_closure);
377 // 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
378 // consequence!). 478 // consequence!).
379 return true; 479 return true;
380 } 480 }
381 481
382 // 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
383 // and the task isn't nestable. 483 // and the task isn't nestable.
384 deferred_non_nestable_work_queue_.push(pending_task); 484 deferred_non_nestable_work_queue_.push(pending_closure);
385 return false; 485 return false;
386 } 486 }
387 487
388 void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) { 488 void MessageLoop::AddToDelayedWorkQueue(const PendingClosure& pending_closure) {
389 // Move to the delayed work queue. Initialize the sequence number 489 // Move to the delayed work queue. Initialize the sequence number
390 // before inserting into the delayed_work_queue_. The sequence number 490 // before inserting into the delayed_work_queue_. The sequence number
391 // is used to faciliate FIFO sorting when two tasks have the same 491 // is used to faciliate FIFO sorting when two tasks have the same
392 // delayed_run_time value. 492 // delayed_run_time value.
393 PendingTask new_pending_task(pending_task); 493 PendingClosure new_pending_closure(pending_closure);
394 new_pending_task.sequence_num = next_sequence_num_++; 494 new_pending_closure.sequence_num = next_sequence_num_++;
395 delayed_work_queue_.push(new_pending_task); 495 delayed_work_queue_.push(new_pending_closure);
396 } 496 }
397 497
398 void MessageLoop::ReloadWorkQueue() { 498 void MessageLoop::ReloadWorkQueue() {
399 // We can improve performance of our loading tasks from incoming_queue_ to 499 // We can improve performance of our loading tasks from incoming_queue_ to
400 // work_queue_ by waiting until the last minute (work_queue_ is empty) to 500 // work_queue_ by waiting until the last minute (work_queue_ is empty) to
401 // load. That reduces the number of locks-per-task significantly when our 501 // load. That reduces the number of locks-per-task significantly when our
402 // queues get large. 502 // queues get large.
403 if (!work_queue_.empty()) 503 if (!work_queue_.empty())
404 return; // Wait till we *really* need to lock and load. 504 return; // Wait till we *really* need to lock and load.
405 505
406 // Acquire all we can from the inter-thread queue with one lock acquisition. 506 // Acquire all we can from the inter-thread queue with one lock acquisition.
407 { 507 {
408 base::AutoLock lock(incoming_queue_lock_); 508 base::AutoLock lock(incoming_queue_lock_);
409 if (incoming_queue_.empty()) 509 if (incoming_queue_.empty())
410 return; 510 return;
411 incoming_queue_.Swap(&work_queue_); // Constant time 511 incoming_queue_.Swap(&work_queue_); // Constant time
412 DCHECK(incoming_queue_.empty()); 512 DCHECK(incoming_queue_.empty());
413 } 513 }
414 } 514 }
415 515
416 bool MessageLoop::DeletePendingTasks() { 516 bool MessageLoop::DeletePendingClosures() {
417 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 #if defined(PURIFY) || defined(USE_HEAPCHECKER)
523 should_leak_tasks_ = false;
524 #else
525 if (RunningOnValgrind())
526 should_leak_tasks_ = false;
527 #endif // defined(OS_POSIX)
418 while (!work_queue_.empty()) { 528 while (!work_queue_.empty()) {
419 PendingTask pending_task = work_queue_.front(); 529 PendingClosure pending_closure = work_queue_.front();
420 work_queue_.pop(); 530 work_queue_.pop();
421 if (!pending_task.delayed_run_time.is_null()) { 531 if (!pending_closure.delayed_run_time.is_null()) {
422 // We want to delete delayed tasks in the same order in which they would 532 // We want to delete delayed tasks in the same order in which they would
423 // normally be deleted in case of any funny dependencies between delayed 533 // normally be deleted in case of any funny dependencies between delayed
424 // tasks. 534 // tasks.
425 AddToDelayedWorkQueue(pending_task); 535 AddToDelayedWorkQueue(pending_closure);
426 } else {
427 // TODO(darin): Delete all tasks once it is safe to do so.
428 // Until it is totally safe, just do it when running Purify or
429 // Valgrind.
430 #if defined(PURIFY) || defined(USE_HEAPCHECKER)
431 delete pending_task.task;
432 #else
433 if (RunningOnValgrind())
434 delete pending_task.task;
435 #endif // defined(OS_POSIX)
436 } 536 }
437 } 537 }
438 did_work |= !deferred_non_nestable_work_queue_.empty(); 538 did_work |= !deferred_non_nestable_work_queue_.empty();
439 while (!deferred_non_nestable_work_queue_.empty()) { 539 while (!deferred_non_nestable_work_queue_.empty()) {
440 // TODO(darin): Delete all tasks once it is safe to do so.
441 // Until it is totaly safe, only delete them under Purify and Valgrind.
442 Task* task = NULL;
443 #if defined(PURIFY) || defined(USE_HEAPCHECKER)
444 task = deferred_non_nestable_work_queue_.front().task;
445 #else
446 if (RunningOnValgrind())
447 task = deferred_non_nestable_work_queue_.front().task;
448 #endif
449 deferred_non_nestable_work_queue_.pop(); 540 deferred_non_nestable_work_queue_.pop();
450 if (task)
451 delete task;
452 } 541 }
453 did_work |= !delayed_work_queue_.empty(); 542 did_work |= !delayed_work_queue_.empty();
543
544 // Historically, we always delete the task regardless of valgrind status. It's
545 // not completely clear why we want to leak them in the loops above. This
546 // code is replicating legacy behavior, and should not be considered
547 // absolutely "correct" behavior.
awong 2011/04/10 15:58:12 Hey Darin, do you know the rationale behind why we
548 should_leak_tasks_ = false;
454 while (!delayed_work_queue_.empty()) { 549 while (!delayed_work_queue_.empty()) {
455 Task* task = delayed_work_queue_.top().task;
456 delayed_work_queue_.pop(); 550 delayed_work_queue_.pop();
457 delete task;
458 } 551 }
552 should_leak_tasks_ = true;
459 return did_work; 553 return did_work;
460 } 554 }
461 555
462 // Possibly called on a background thread! 556 TimeTicks MessageLoop::CalculateDelayedRuntime(int64 delay_ms) {
463 void MessageLoop::PostTask_Helper( 557 TimeTicks delayed_run_time;
464 const tracked_objects::Location& from_here, Task* task, int64 delay_ms,
465 bool nestable) {
466 task->SetBirthPlace(from_here);
467
468 PendingTask pending_task(task, nestable);
469
470 if (delay_ms > 0) { 558 if (delay_ms > 0) {
471 pending_task.delayed_run_time = 559 delayed_run_time =
472 TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms); 560 TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms);
473 561
474 #if defined(OS_WIN) 562 #if defined(OS_WIN)
475 if (high_resolution_timer_expiration_.is_null()) { 563 if (high_resolution_timer_expiration_.is_null()) {
476 // Windows timers are granular to 15.6ms. If we only set high-res 564 // Windows timers are granular to 15.6ms. If we only set high-res
477 // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms, 565 // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms,
478 // which as a percentage is pretty inaccurate. So enable high 566 // which as a percentage is pretty inaccurate. So enable high
479 // res timers for any timer which is within 2x of the granularity. 567 // res timers for any timer which is within 2x of the granularity.
480 // This is a tradeoff between accuracy and power management. 568 // This is a tradeoff between accuracy and power management.
481 bool needs_high_res_timers = 569 bool needs_high_res_timers =
(...skipping 11 matching lines...) Expand all
493 581
494 #if defined(OS_WIN) 582 #if defined(OS_WIN)
495 if (!high_resolution_timer_expiration_.is_null()) { 583 if (!high_resolution_timer_expiration_.is_null()) {
496 if (TimeTicks::Now() > high_resolution_timer_expiration_) { 584 if (TimeTicks::Now() > high_resolution_timer_expiration_) {
497 base::Time::ActivateHighResolutionTimer(false); 585 base::Time::ActivateHighResolutionTimer(false);
498 high_resolution_timer_expiration_ = TimeTicks(); 586 high_resolution_timer_expiration_ = TimeTicks();
499 } 587 }
500 } 588 }
501 #endif 589 #endif
502 590
591 return delayed_run_time;
592 }
593
594 // Possibly called on a background thread!
595 void MessageLoop::AddToIncomingQueue(PendingClosure* pending_closure) {
503 // Warning: Don't try to short-circuit, and handle this thread's tasks more 596 // Warning: Don't try to short-circuit, and handle this thread's tasks more
504 // directly, as it could starve handling of foreign threads. Put every task 597 // directly, as it could starve handling of foreign threads. Put every task
505 // into this queue. 598 // into this queue.
506 599
507 scoped_refptr<base::MessagePump> pump; 600 scoped_refptr<base::MessagePump> pump;
508 { 601 {
509 base::AutoLock locked(incoming_queue_lock_); 602 base::AutoLock locked(incoming_queue_lock_);
510 603
511 bool was_empty = incoming_queue_.empty(); 604 bool was_empty = incoming_queue_.empty();
512 incoming_queue_.push(pending_task); 605 incoming_queue_.push(*pending_closure);
606 pending_closure->closure.Reset();
513 if (!was_empty) 607 if (!was_empty)
514 return; // Someone else should have started the sub-pump. 608 return; // Someone else should have started the sub-pump.
515 609
516 pump = pump_; 610 pump = pump_;
517 } 611 }
518 // Since the incoming_queue_ may contain a task that destroys this message 612 // Since the incoming_queue_ may contain a task that destroys this message
519 // loop, we cannot exit incoming_queue_lock_ until we are done with |this|. 613 // loop, we cannot exit incoming_queue_lock_ until we are done with |this|.
520 // We use a stack-based reference to the message pump so that we can call 614 // We use a stack-based reference to the message pump so that we can call
521 // ScheduleWork outside of incoming_queue_lock_. 615 // ScheduleWork outside of incoming_queue_lock_.
522 616
(...skipping 28 matching lines...) Expand all
551 return false; 645 return false;
552 } 646 }
553 647
554 for (;;) { 648 for (;;) {
555 ReloadWorkQueue(); 649 ReloadWorkQueue();
556 if (work_queue_.empty()) 650 if (work_queue_.empty())
557 break; 651 break;
558 652
559 // Execute oldest task. 653 // Execute oldest task.
560 do { 654 do {
561 PendingTask pending_task = work_queue_.front(); 655 PendingClosure pending_closure = work_queue_.front();
562 work_queue_.pop(); 656 work_queue_.pop();
563 if (!pending_task.delayed_run_time.is_null()) { 657 if (!pending_closure.delayed_run_time.is_null()) {
564 AddToDelayedWorkQueue(pending_task); 658 AddToDelayedWorkQueue(pending_closure);
565 // If we changed the topmost task, then it is time to re-schedule. 659 // If we changed the topmost task, then it is time to re-schedule.
566 if (delayed_work_queue_.top().task == pending_task.task) 660 if (delayed_work_queue_.top().closure.Equals(pending_closure.closure))
567 pump_->ScheduleDelayedWork(pending_task.delayed_run_time); 661 pump_->ScheduleDelayedWork(pending_closure.delayed_run_time);
568 } else { 662 } else {
569 if (DeferOrRunPendingTask(pending_task)) 663 if (DeferOrRunPendingClosure(pending_closure))
570 return true; 664 return true;
571 } 665 }
572 } while (!work_queue_.empty()); 666 } while (!work_queue_.empty());
573 } 667 }
574 668
575 // Nothing happened. 669 // Nothing happened.
576 return false; 670 return false;
577 } 671 }
578 672
579 bool MessageLoop::DoDelayedWork(base::TimeTicks* next_delayed_work_time) { 673 bool MessageLoop::DoDelayedWork(TimeTicks* next_delayed_work_time) {
580 if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) { 674 if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) {
581 recent_time_ = *next_delayed_work_time = TimeTicks(); 675 recent_time_ = *next_delayed_work_time = TimeTicks();
582 return false; 676 return false;
583 } 677 }
584 678
585 // When we "fall behind," there will be a lot of tasks in the delayed work 679 // When we "fall behind," there will be a lot of tasks in the delayed work
586 // queue that are ready to run. To increase efficiency when we fall behind, 680 // queue that are ready to run. To increase efficiency when we fall behind,
587 // we will only call Time::Now() intermittently, and then process all tasks 681 // we will only call Time::Now() intermittently, and then process all tasks
588 // that are ready to run before calling it again. As a result, the more we 682 // that are ready to run before calling it again. As a result, the more we
589 // fall behind (and have a lot of ready-to-run delayed tasks), the more 683 // fall behind (and have a lot of ready-to-run delayed tasks), the more
590 // efficient we'll be at handling the tasks. 684 // efficient we'll be at handling the tasks.
591 685
592 TimeTicks next_run_time = delayed_work_queue_.top().delayed_run_time; 686 TimeTicks next_run_time = delayed_work_queue_.top().delayed_run_time;
593 if (next_run_time > recent_time_) { 687 if (next_run_time > recent_time_) {
594 recent_time_ = TimeTicks::Now(); // Get a better view of Now(); 688 recent_time_ = TimeTicks::Now(); // Get a better view of Now();
595 if (next_run_time > recent_time_) { 689 if (next_run_time > recent_time_) {
596 *next_delayed_work_time = next_run_time; 690 *next_delayed_work_time = next_run_time;
597 return false; 691 return false;
598 } 692 }
599 } 693 }
600 694
601 PendingTask pending_task = delayed_work_queue_.top(); 695 PendingClosure pending_closure = delayed_work_queue_.top();
602 delayed_work_queue_.pop(); 696 delayed_work_queue_.pop();
603 697
604 if (!delayed_work_queue_.empty()) 698 if (!delayed_work_queue_.empty())
605 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time; 699 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
606 700
607 return DeferOrRunPendingTask(pending_task); 701 return DeferOrRunPendingClosure(pending_closure);
608 } 702 }
609 703
610 bool MessageLoop::DoIdleWork() { 704 bool MessageLoop::DoIdleWork() {
611 if (ProcessNextDelayedNonNestableTask()) 705 if (ProcessNextDelayedNonNestableTask())
612 return true; 706 return true;
613 707
614 if (state_->quit_received) 708 if (state_->quit_received)
615 pump_->Quit(); 709 pump_->Quit();
616 710
617 return false; 711 return false;
(...skipping 17 matching lines...) Expand all
635 #if !defined(OS_MACOSX) 729 #if !defined(OS_MACOSX)
636 dispatcher = NULL; 730 dispatcher = NULL;
637 #endif 731 #endif
638 } 732 }
639 733
640 MessageLoop::AutoRunState::~AutoRunState() { 734 MessageLoop::AutoRunState::~AutoRunState() {
641 loop_->state_ = previous_state_; 735 loop_->state_ = previous_state_;
642 } 736 }
643 737
644 //------------------------------------------------------------------------------ 738 //------------------------------------------------------------------------------
645 // MessageLoop::PendingTask 739 // MessageLoop::PendingClosure
646 740
647 bool MessageLoop::PendingTask::operator<(const PendingTask& other) const { 741 MessageLoop::PendingClosure::PendingClosure(
742 const base::Closure& closure,
743 const tracked_objects::Location& posted_from,
744 TimeTicks delayed_run_time,
745 bool nestable)
746 : closure(closure),
747 time_posted(TimeTicks::Now()),
748 delayed_run_time(delayed_run_time), sequence_num(0),
darin (slow to review) 2011/04/09 04:21:58 nit: new line before sequence_num(0)
awong 2011/04/10 15:58:12 Done.
749 nestable(nestable) {
750 #if defined(TRACK_ALL_TASK_OBJECTS)
751 if (tracked_objects::ThreadData::IsActive()) {
752 tracked_objects::ThreadData* current_thread_data =
753 tracked_objects::ThreadData::current();
754 if (current_thread_data) {
755 post_births = current_thread_data->TallyABirth(posted_from);
756 } else {
757 // Shutdown started, and this thread wasn't registered.
758 post_births = NULL;
759 }
760 }
761 #endif // defined(TRACK_ALL_TASK_OBJECTS)
762 }
763
764 bool MessageLoop::PendingClosure::operator<(const PendingClosure& other) const {
648 // Since the top of a priority queue is defined as the "greatest" element, we 765 // Since the top of a priority queue is defined as the "greatest" element, we
649 // need to invert the comparison here. We want the smaller time to be at the 766 // need to invert the comparison here. We want the smaller time to be at the
650 // top of the heap. 767 // top of the heap.
651 768
652 if (delayed_run_time < other.delayed_run_time) 769 if (delayed_run_time < other.delayed_run_time)
653 return false; 770 return false;
654 771
655 if (delayed_run_time > other.delayed_run_time) 772 if (delayed_run_time > other.delayed_run_time)
656 return true; 773 return true;
657 774
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 Watcher *delegate) { 830 Watcher *delegate) {
714 return pump_libevent()->WatchFileDescriptor( 831 return pump_libevent()->WatchFileDescriptor(
715 fd, 832 fd,
716 persistent, 833 persistent,
717 static_cast<base::MessagePumpLibevent::Mode>(mode), 834 static_cast<base::MessagePumpLibevent::Mode>(mode),
718 controller, 835 controller,
719 delegate); 836 delegate);
720 } 837 }
721 838
722 #endif 839 #endif
OLDNEW
« no previous file with comments | « base/message_loop.h ('k') | base/message_loop_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698