OLD | NEW |
---|---|
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 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 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |