OLD | NEW |
1 // Copyright (c) 2011 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 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 | 78 |
79 // A few events we handle (kindred to messages), and used to profile actions. | 79 // A few events we handle (kindred to messages), and used to profile actions. |
80 VALUE_TO_NUMBER_AND_NAME(kTaskRunEvent) | 80 VALUE_TO_NUMBER_AND_NAME(kTaskRunEvent) |
81 VALUE_TO_NUMBER_AND_NAME(kTimerEvent) | 81 VALUE_TO_NUMBER_AND_NAME(kTimerEvent) |
82 | 82 |
83 {-1, NULL} // The list must be null terminated, per API to histogram. | 83 {-1, NULL} // The list must be null terminated, per API to histogram. |
84 }; | 84 }; |
85 | 85 |
86 bool enable_histogrammer_ = false; | 86 bool enable_histogrammer_ = false; |
87 | 87 |
88 // TODO(ajwong): This is one use case for having a Owned() tag that behaves | |
89 // like a "Unique" pointer. If we had that, and Tasks were always safe to | |
90 // delete on MessageLoop shutdown, this class could just be a function. | |
91 class TaskClosureAdapter : public base::RefCounted<TaskClosureAdapter> { | |
92 public: | |
93 // |should_leak_task| points to a flag variable that can be used to determine | |
94 // if this class should leak the Task on destruction. This is important | |
95 // at MessageLoop shutdown since not all tasks can be safely deleted without | |
96 // running. See MessageLoop::DeletePendingTasks() for the exact behavior | |
97 // of when a Task should be deleted. It is subtle. | |
98 TaskClosureAdapter(Task* task, bool* should_leak_task) | |
99 : task_(task), | |
100 should_leak_task_(should_leak_task) { | |
101 } | |
102 | |
103 void Run() { | |
104 task_->Run(); | |
105 delete task_; | |
106 task_ = NULL; | |
107 } | |
108 | |
109 private: | |
110 friend class base::RefCounted<TaskClosureAdapter>; | |
111 | |
112 ~TaskClosureAdapter() { | |
113 if (!*should_leak_task_) { | |
114 delete task_; | |
115 } | |
116 } | |
117 | |
118 Task* task_; | |
119 bool* should_leak_task_; | |
120 }; | |
121 | |
122 } // namespace | 88 } // namespace |
123 | 89 |
124 //------------------------------------------------------------------------------ | 90 //------------------------------------------------------------------------------ |
125 | 91 |
126 #if defined(OS_WIN) | 92 #if defined(OS_WIN) |
127 | 93 |
128 // Upon a SEH exception in this thread, it restores the original unhandled | 94 // Upon a SEH exception in this thread, it restores the original unhandled |
129 // exception filter. | 95 // exception filter. |
130 static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) { | 96 static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) { |
131 ::SetUnhandledExceptionFilter(old_filter); | 97 ::SetUnhandledExceptionFilter(old_filter); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 void MessageLoop::RemoveDestructionObserver( | 230 void MessageLoop::RemoveDestructionObserver( |
265 DestructionObserver* destruction_observer) { | 231 DestructionObserver* destruction_observer) { |
266 DCHECK_EQ(this, current()); | 232 DCHECK_EQ(this, current()); |
267 destruction_observers_.RemoveObserver(destruction_observer); | 233 destruction_observers_.RemoveObserver(destruction_observer); |
268 } | 234 } |
269 | 235 |
270 void MessageLoop::PostTask( | 236 void MessageLoop::PostTask( |
271 const tracked_objects::Location& from_here, Task* task) { | 237 const tracked_objects::Location& from_here, Task* task) { |
272 CHECK(task); | 238 CHECK(task); |
273 PendingTask pending_task( | 239 PendingTask pending_task( |
274 base::Bind(&TaskClosureAdapter::Run, | 240 base::Bind( |
275 new TaskClosureAdapter(task, &should_leak_tasks_)), | 241 &base::subtle::TaskClosureAdapter::Run, |
| 242 new base::subtle::TaskClosureAdapter(task, &should_leak_tasks_)), |
276 from_here, | 243 from_here, |
277 CalculateDelayedRuntime(0), true); | 244 CalculateDelayedRuntime(0), true); |
278 AddToIncomingQueue(&pending_task); | 245 AddToIncomingQueue(&pending_task); |
279 } | 246 } |
280 | 247 |
281 void MessageLoop::PostDelayedTask( | 248 void MessageLoop::PostDelayedTask( |
282 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { | 249 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { |
283 CHECK(task); | 250 CHECK(task); |
284 PendingTask pending_task( | 251 PendingTask pending_task( |
285 base::Bind(&TaskClosureAdapter::Run, | 252 base::Bind( |
286 new TaskClosureAdapter(task, &should_leak_tasks_)), | 253 &base::subtle::TaskClosureAdapter::Run, |
| 254 new base::subtle::TaskClosureAdapter(task, &should_leak_tasks_)), |
287 from_here, | 255 from_here, |
288 CalculateDelayedRuntime(delay_ms), true); | 256 CalculateDelayedRuntime(delay_ms), true); |
289 AddToIncomingQueue(&pending_task); | 257 AddToIncomingQueue(&pending_task); |
290 } | 258 } |
291 | 259 |
292 void MessageLoop::PostNonNestableTask( | 260 void MessageLoop::PostNonNestableTask( |
293 const tracked_objects::Location& from_here, Task* task) { | 261 const tracked_objects::Location& from_here, Task* task) { |
294 CHECK(task); | 262 CHECK(task); |
295 PendingTask pending_task( | 263 PendingTask pending_task( |
296 base::Bind(&TaskClosureAdapter::Run, | 264 base::Bind( |
297 new TaskClosureAdapter(task, &should_leak_tasks_)), | 265 &base::subtle::TaskClosureAdapter::Run, |
| 266 new base::subtle::TaskClosureAdapter(task, &should_leak_tasks_)), |
298 from_here, | 267 from_here, |
299 CalculateDelayedRuntime(0), false); | 268 CalculateDelayedRuntime(0), false); |
300 AddToIncomingQueue(&pending_task); | 269 AddToIncomingQueue(&pending_task); |
301 } | 270 } |
302 | 271 |
303 void MessageLoop::PostNonNestableDelayedTask( | 272 void MessageLoop::PostNonNestableDelayedTask( |
304 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { | 273 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) { |
305 CHECK(task); | 274 CHECK(task); |
306 PendingTask pending_task( | 275 PendingTask pending_task( |
307 base::Bind(&TaskClosureAdapter::Run, | 276 base::Bind( |
308 new TaskClosureAdapter(task, &should_leak_tasks_)), | 277 &base::subtle::TaskClosureAdapter::Run, |
| 278 new base::subtle::TaskClosureAdapter(task, &should_leak_tasks_)), |
309 from_here, | 279 from_here, |
310 CalculateDelayedRuntime(delay_ms), false); | 280 CalculateDelayedRuntime(delay_ms), false); |
311 AddToIncomingQueue(&pending_task); | 281 AddToIncomingQueue(&pending_task); |
312 } | 282 } |
313 | 283 |
314 void MessageLoop::PostTask( | 284 void MessageLoop::PostTask( |
315 const tracked_objects::Location& from_here, const base::Closure& task) { | 285 const tracked_objects::Location& from_here, const base::Closure& task) { |
316 CHECK(!task.is_null()); | 286 CHECK(!task.is_null()); |
317 PendingTask pending_task(task, from_here, CalculateDelayedRuntime(0), true); | 287 PendingTask pending_task(task, from_here, CalculateDelayedRuntime(0), true); |
318 AddToIncomingQueue(&pending_task); | 288 AddToIncomingQueue(&pending_task); |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 base::debug::Alias(&program_counter); | 449 base::debug::Alias(&program_counter); |
480 | 450 |
481 HistogramEvent(kTaskRunEvent); | 451 HistogramEvent(kTaskRunEvent); |
482 FOR_EACH_OBSERVER(TaskObserver, task_observers_, | 452 FOR_EACH_OBSERVER(TaskObserver, task_observers_, |
483 WillProcessTask(pending_task.time_posted)); | 453 WillProcessTask(pending_task.time_posted)); |
484 pending_task.task.Run(); | 454 pending_task.task.Run(); |
485 FOR_EACH_OBSERVER(TaskObserver, task_observers_, | 455 FOR_EACH_OBSERVER(TaskObserver, task_observers_, |
486 DidProcessTask(pending_task.time_posted)); | 456 DidProcessTask(pending_task.time_posted)); |
487 | 457 |
488 #if defined(TRACK_ALL_TASK_OBJECTS) | 458 #if defined(TRACK_ALL_TASK_OBJECTS) |
489 if (tracked_objects::ThreadData::IsActive() && pending_task.post_births) { | 459 tracked_objects::ThreadData::TallyADeathIfActive( |
490 tracked_objects::ThreadData::current()->TallyADeath( | 460 pending_task.post_births, |
491 *pending_task.post_births, | 461 TimeTicks::Now() - pending_task.time_posted); |
492 TimeTicks::Now() - pending_task.time_posted); | |
493 } | |
494 #endif // defined(TRACK_ALL_TASK_OBJECTS) | 462 #endif // defined(TRACK_ALL_TASK_OBJECTS) |
495 | 463 |
496 nestable_tasks_allowed_ = true; | 464 nestable_tasks_allowed_ = true; |
497 } | 465 } |
498 | 466 |
499 bool MessageLoop::DeferOrRunPendingTask( | 467 bool MessageLoop::DeferOrRunPendingTask( |
500 const PendingTask& pending_task) { | 468 const PendingTask& pending_task) { |
501 if (pending_task.nestable || state_->run_depth == 1) { | 469 if (pending_task.nestable || state_->run_depth == 1) { |
502 RunTask(pending_task); | 470 RunTask(pending_task); |
503 // Show that we ran a task (Note: a new one might arrive as a | 471 // Show that we ran a task (Note: a new one might arrive as a |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 const tracked_objects::Location& posted_from, | 741 const tracked_objects::Location& posted_from, |
774 TimeTicks delayed_run_time, | 742 TimeTicks delayed_run_time, |
775 bool nestable) | 743 bool nestable) |
776 : task(task), | 744 : task(task), |
777 time_posted(TimeTicks::Now()), | 745 time_posted(TimeTicks::Now()), |
778 delayed_run_time(delayed_run_time), | 746 delayed_run_time(delayed_run_time), |
779 sequence_num(0), | 747 sequence_num(0), |
780 nestable(nestable), | 748 nestable(nestable), |
781 birth_program_counter(posted_from.program_counter()) { | 749 birth_program_counter(posted_from.program_counter()) { |
782 #if defined(TRACK_ALL_TASK_OBJECTS) | 750 #if defined(TRACK_ALL_TASK_OBJECTS) |
783 post_births = NULL; | 751 post_births = tracked_objects::ThreadData::TallyABirthIfActive(posted_from); |
784 if (tracked_objects::ThreadData::IsActive()) { | |
785 tracked_objects::ThreadData* current_thread_data = | |
786 tracked_objects::ThreadData::current(); | |
787 if (current_thread_data) { | |
788 post_births = current_thread_data->TallyABirth(posted_from); | |
789 } | |
790 } | |
791 #endif // defined(TRACK_ALL_TASK_OBJECTS) | 752 #endif // defined(TRACK_ALL_TASK_OBJECTS) |
792 } | 753 } |
793 | 754 |
794 MessageLoop::PendingTask::~PendingTask() { | 755 MessageLoop::PendingTask::~PendingTask() { |
795 } | 756 } |
796 | 757 |
797 bool MessageLoop::PendingTask::operator<(const PendingTask& other) const { | 758 bool MessageLoop::PendingTask::operator<(const PendingTask& other) const { |
798 // Since the top of a priority queue is defined as the "greatest" element, we | 759 // Since the top of a priority queue is defined as the "greatest" element, we |
799 // need to invert the comparison here. We want the smaller time to be at the | 760 // need to invert the comparison here. We want the smaller time to be at the |
800 // top of the heap. | 761 // top of the heap. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 Watcher *delegate) { | 818 Watcher *delegate) { |
858 return pump_libevent()->WatchFileDescriptor( | 819 return pump_libevent()->WatchFileDescriptor( |
859 fd, | 820 fd, |
860 persistent, | 821 persistent, |
861 static_cast<base::MessagePumpLibevent::Mode>(mode), | 822 static_cast<base::MessagePumpLibevent::Mode>(mode), |
862 controller, | 823 controller, |
863 delegate); | 824 delegate); |
864 } | 825 } |
865 | 826 |
866 #endif | 827 #endif |
OLD | NEW |