Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 636 lines (527 sloc) 19.531 kb
96f302f Adds some ifdefs so that test_shell can be compiled on linux
sky@chromium.org authored
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
1457f56 Use a more compact license header in source files.
license.bot authored
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
d7cae12 Add base to the repository.
initial.commit authored
4
44f6598 rollback portions of r928 to test to see if it impacts perf
darin@google.com authored
5 #include "base/message_loop.h"
6
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
7 #include <algorithm>
8
d3da573 Fix the final gcc warnings in base and net. Provide some macros to sele...
mmentovai@google.com authored
9 #include "base/compiler_specific.h"
3a70efc Move a bunch of code from the old to new TLS interface.
deanm@chromium.org authored
10 #include "base/lazy_instance.h"
d7cae12 Add base to the repository.
initial.commit authored
11 #include "base/logging.h"
f1f0828 Define MessagePumpDefault and use it to implement MessageLoop on non-Win...
darin@google.com authored
12 #include "base/message_pump_default.h"
d7cae12 Add base to the repository.
initial.commit authored
13 #include "base/string_util.h"
3a70efc Move a bunch of code from the old to new TLS interface.
deanm@chromium.org authored
14 #include "base/thread_local.h"
d7cae12 Add base to the repository.
initial.commit authored
15
9f9aa25 Mac-specific CFRunLoop-based MessagePump implementation
mark@chromium.org authored
16 #if defined(OS_MACOSX)
17 #include "base/message_pump_mac.h"
18 #endif
33e4111 Use libevent, second try. Changes this time:
dkegel@google.com authored
19 #if defined(OS_POSIX)
20 #include "base/message_pump_libevent.h"
d756fa2 During shutdown delete any pending tasks if running under Valgrind.
kuchhal@chromium.org authored
21 #include "base/third_party/valgrind/valgrind.h"
33e4111 Use libevent, second try. Changes this time:
dkegel@google.com authored
22 #endif
b981968 Changes to base/ from a combination of FreeBSD and OpenBSD patches.
evan@chromium.org authored
23 #if defined(OS_POSIX) && !defined(OS_MACOSX)
af751d8 Implement MessageLoopForUI using GLib. This gets some exercise from
dsh@google.com authored
24 #include "base/message_pump_glib.h"
25 #endif
33e4111 Use libevent, second try. Changes this time:
dkegel@google.com authored
26
8ccfd90 Move Time, TimeDelta and TimeTicks into namespace base.
dsh@google.com authored
27 using base::Time;
28 using base::TimeDelta;
29
3a70efc Move a bunch of code from the old to new TLS interface.
deanm@chromium.org authored
30 // A lazily created thread local storage for quick access to a thread's message
31 // loop, if one exists. This should be safe and free of static constructors.
32 static base::LazyInstance<base::ThreadLocalPointer<MessageLoop> > lazy_tls_ptr(
33 base::LINKER_INITIALIZED);
d7cae12 Add base to the repository.
initial.commit authored
34
35 //------------------------------------------------------------------------------
36
37 // Logical events for Histogram profiling. Run with -message-loop-histogrammer
38 // to get an accounting of messages and actions taken on each thread.
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
39 static const int kTaskRunEvent = 0x1;
40 static const int kTimerEvent = 0x2;
d7cae12 Add base to the repository.
initial.commit authored
41
42 // Provide range of message IDs for use in histogramming and debug display.
43 static const int kLeastNonZeroMessageId = 1;
44 static const int kMaxMessageId = 1099;
45 static const int kNumberOfDistinctMessagesDisplayed = 1100;
46
47 //------------------------------------------------------------------------------
48
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
49 #if defined(OS_WIN)
44f6598 rollback portions of r928 to test to see if it impacts perf
darin@google.com authored
50
d7cae12 Add base to the repository.
initial.commit authored
51 // Upon a SEH exception in this thread, it restores the original unhandled
52 // exception filter.
53 static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) {
54 ::SetUnhandledExceptionFilter(old_filter);
55 return EXCEPTION_CONTINUE_SEARCH;
56 }
57
58 // Retrieves a pointer to the current unhandled exception filter. There
59 // is no standalone getter method.
60 static LPTOP_LEVEL_EXCEPTION_FILTER GetTopSEHFilter() {
61 LPTOP_LEVEL_EXCEPTION_FILTER top_filter = NULL;
62 top_filter = ::SetUnhandledExceptionFilter(0);
63 ::SetUnhandledExceptionFilter(top_filter);
64 return top_filter;
65 }
66
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
67 #endif // defined(OS_WIN)
68
d7cae12 Add base to the repository.
initial.commit authored
69 //------------------------------------------------------------------------------
70
3a70efc Move a bunch of code from the old to new TLS interface.
deanm@chromium.org authored
71 // static
72 MessageLoop* MessageLoop::current() {
73 // TODO(darin): sadly, we cannot enable this yet since people call us even
74 // when they have no intention of using us.
75 //DCHECK(loop) << "Ouch, did you forget to initialize me?";
76 return lazy_tls_ptr.Pointer()->Get();
77 }
78
5da457d Allow consumers of MessageLoop to specify the type of MessageLoop they w...
darin@google.com authored
79 MessageLoop::MessageLoop(Type type)
80 : type_(type),
1b14c52 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@760 0039d316-1c4b-42...
darin@google.com authored
81 nestable_tasks_allowed_(true),
f1f0828 Define MessagePumpDefault and use it to implement MessageLoop on non-Win...
darin@google.com authored
82 exception_restoration_(false),
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
83 state_(NULL),
84 next_sequence_num_(0) {
3a70efc Move a bunch of code from the old to new TLS interface.
deanm@chromium.org authored
85 DCHECK(!current()) << "should only have one message loop per thread";
86 lazy_tls_ptr.Pointer()->Set(this);
5da457d Allow consumers of MessageLoop to specify the type of MessageLoop they w...
darin@google.com authored
87
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
88 #if defined(OS_WIN)
d0773ca As an intermediate step towards having a message pump handling IO throug...
rvargas@google.com authored
89 // TODO(rvargas): Get rid of the OS guards.
6debf90 Switch SharedTimerWin over to using PostDelayedTask. I made some tweaks...
darin@google.com authored
90 if (type_ == TYPE_DEFAULT) {
91 pump_ = new base::MessagePumpDefault();
d0773ca As an intermediate step towards having a message pump handling IO throug...
rvargas@google.com authored
92 } else if (type_ == TYPE_IO) {
93 pump_ = new base::MessagePumpForIO();
6debf90 Switch SharedTimerWin over to using PostDelayedTask. I made some tweaks...
darin@google.com authored
94 } else {
d0773ca As an intermediate step towards having a message pump handling IO throug...
rvargas@google.com authored
95 DCHECK(type_ == TYPE_UI);
96 pump_ = new base::MessagePumpForUI();
6debf90 Switch SharedTimerWin over to using PostDelayedTask. I made some tweaks...
darin@google.com authored
97 }
33e4111 Use libevent, second try. Changes this time:
dkegel@google.com authored
98 #elif defined(OS_POSIX)
9f9aa25 Mac-specific CFRunLoop-based MessagePump implementation
mark@chromium.org authored
99 if (type_ == TYPE_UI) {
af751d8 Implement MessageLoopForUI using GLib. This gets some exercise from
dsh@google.com authored
100 #if defined(OS_MACOSX)
9f9aa25 Mac-specific CFRunLoop-based MessagePump implementation
mark@chromium.org authored
101 pump_ = base::MessagePumpMac::Create();
b981968 Changes to base/ from a combination of FreeBSD and OpenBSD patches.
evan@chromium.org authored
102 #else
af751d8 Implement MessageLoopForUI using GLib. This gets some exercise from
dsh@google.com authored
103 pump_ = new base::MessagePumpForUI();
b981968 Changes to base/ from a combination of FreeBSD and OpenBSD patches.
evan@chromium.org authored
104 #endif
af751d8 Implement MessageLoopForUI using GLib. This gets some exercise from
dsh@google.com authored
105 } else if (type_ == TYPE_IO) {
33e4111 Use libevent, second try. Changes this time:
dkegel@google.com authored
106 pump_ = new base::MessagePumpLibevent();
107 } else {
108 pump_ = new base::MessagePumpDefault();
109 }
9f9aa25 Mac-specific CFRunLoop-based MessagePump implementation
mark@chromium.org authored
110 #endif // OS_POSIX
d7cae12 Add base to the repository.
initial.commit authored
111 }
112
113 MessageLoop::~MessageLoop() {
114 DCHECK(this == current());
4e294f8 ObjectWatcher needs to know when the current thread's MessageLoop is bei...
darin@google.com authored
115
116 // Let interested parties have one last shot at accessing this.
117 FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_,
118 WillDestroyCurrentMessageLoop());
119
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
120 DCHECK(!state_);
4e294f8 ObjectWatcher needs to know when the current thread's MessageLoop is bei...
darin@google.com authored
121
5ffa1ca Put back r1891 with some task deletion disabled to maintain backwards co...
darin@chromium.org authored
122 // Clean up any unprocessed tasks, but take care: deleting a task could
123 // result in the addition of more tasks (e.g., via DeleteSoon). We set a
124 // limit on the number of times we will allow a deleted task to generate more
125 // tasks. Normally, we should only pass through this loop once or twice. If
126 // we end up hitting the loop limit, then it is probably due to one task that
127 // is being stubborn. Inspect the queues to see who is left.
128 bool did_work;
129 for (int i = 0; i < 100; ++i) {
130 DeletePendingTasks();
131 ReloadWorkQueue();
132 // If we end up with empty queues, then break out of the loop.
133 did_work = DeletePendingTasks();
134 if (!did_work)
135 break;
23ec520 rollback r1891
darin@google.com authored
136 }
5ffa1ca Put back r1891 with some task deletion disabled to maintain backwards co...
darin@chromium.org authored
137 DCHECK(!did_work);
138
139 // OK, now make it so that no one can find us.
b2ba728 Fix a mis-merge in TLS changes.
deanm@chromium.org authored
140 lazy_tls_ptr.Pointer()->Set(NULL);
d7cae12 Add base to the repository.
initial.commit authored
141 }
142
4e294f8 ObjectWatcher needs to know when the current thread's MessageLoop is bei...
darin@google.com authored
143 void MessageLoop::AddDestructionObserver(DestructionObserver *obs) {
144 DCHECK(this == current());
145 destruction_observers_.AddObserver(obs);
146 }
147
148 void MessageLoop::RemoveDestructionObserver(DestructionObserver *obs) {
149 DCHECK(this == current());
150 destruction_observers_.RemoveObserver(obs);
151 }
152
d7cae12 Add base to the repository.
initial.commit authored
153 void MessageLoop::Run() {
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
154 AutoRunState save_state(this);
155 RunHandler();
16a2642 (Re-landing of) Support RunOnce() in message loop.
jar@google.com authored
156 }
157
9dfbbd6 Support RanAllPending() rather than RunOnce(), and integrated into ipc_s...
jar@google.com authored
158 void MessageLoop::RunAllPending() {
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
159 AutoRunState save_state(this);
160 state_->quit_received = true; // Means run until we would otherwise block.
161 RunHandler();
d7cae12 Add base to the repository.
initial.commit authored
162 }
163
164 // Runs the loop in two different SEH modes:
165 // enable_SEH_restoration_ = false : any unhandled exception goes to the last
166 // one that calls SetUnhandledExceptionFilter().
167 // enable_SEH_restoration_ = true : any unhandled exception goes to the filter
168 // that was existed before the loop was run.
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
169 void MessageLoop::RunHandler() {
170 #if defined(OS_WIN)
d7cae12 Add base to the repository.
initial.commit authored
171 if (exception_restoration_) {
46d3bbf Move creation of SEH frame into a separate funcion.For any function that...
stoyan@google.com authored
172 RunInternalInSEHFrame();
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
173 return;
d7cae12 Add base to the repository.
initial.commit authored
174 }
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
175 #endif
176
177 RunInternal();
d7cae12 Add base to the repository.
initial.commit authored
178 }
46d3bbf Move creation of SEH frame into a separate funcion.For any function that...
stoyan@google.com authored
179 //------------------------------------------------------------------------------
180 #if defined(OS_WIN)
181 __declspec(noinline) void MessageLoop::RunInternalInSEHFrame() {
182 LPTOP_LEVEL_EXCEPTION_FILTER current_filter = GetTopSEHFilter();
183 __try {
184 RunInternal();
185 } __except(SEHFilter(current_filter)) {
186 }
187 return;
188 }
189 #endif
d7cae12 Add base to the repository.
initial.commit authored
190 //------------------------------------------------------------------------------
191
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
192 void MessageLoop::RunInternal() {
d7cae12 Add base to the repository.
initial.commit authored
193 DCHECK(this == current());
e2e3501 Rollback message loop test
jar@google.com authored
194
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
195 StartHistogrammer();
44f6598 rollback portions of r928 to test to see if it impacts perf
darin@google.com authored
196
b981968 Changes to base/ from a combination of FreeBSD and OpenBSD patches.
evan@chromium.org authored
197 #if !defined(OS_MACOSX)
4cbc26c This CL adds accelerators to the Linux toolkit views.
jcampan@chromium.org authored
198 if (state_->dispatcher && type() == TYPE_UI) {
199 static_cast<base::MessagePumpForUI*>(pump_.get())->
200 RunWithDispatcher(this, state_->dispatcher);
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
201 return;
9dfbbd6 Support RanAllPending() rather than RunOnce(), and integrated into ipc_s...
jar@google.com authored
202 }
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
203 #endif
b3298a6 Add FD watching support to message_pump_libevent.
jeremy@chromium.org authored
204
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
205 pump_->Run(this);
6d37fcf Rollback 109
jar@google.com authored
206 }
f53d43d M base/message_loop.h
jar@google.com authored
207
16a2642 (Re-landing of) Support RunOnce() in message loop.
jar@google.com authored
208 //------------------------------------------------------------------------------
209 // Wrapper functions for use in above message loop framework.
210
d7cae12 Add base to the repository.
initial.commit authored
211 bool MessageLoop::ProcessNextDelayedNonNestableTask() {
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
212 if (state_->run_depth != 1)
d7cae12 Add base to the repository.
initial.commit authored
213 return false;
214
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
215 if (deferred_non_nestable_work_queue_.empty())
d7cae12 Add base to the repository.
initial.commit authored
216 return false;
b3298a6 Add FD watching support to message_pump_libevent.
jeremy@chromium.org authored
217
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
218 Task* task = deferred_non_nestable_work_queue_.front().task;
219 deferred_non_nestable_work_queue_.pop();
b3298a6 Add FD watching support to message_pump_libevent.
jeremy@chromium.org authored
220
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
221 RunTask(task);
d7cae12 Add base to the repository.
initial.commit authored
222 return true;
223 }
224
225 //------------------------------------------------------------------------------
226
227 void MessageLoop::Quit() {
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
228 DCHECK(current() == this);
229 if (state_) {
230 state_->quit_received = true;
231 } else {
232 NOTREACHED() << "Must be inside Run to call Quit";
d7cae12 Add base to the repository.
initial.commit authored
233 }
234 }
235
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
236 void MessageLoop::PostTask(
237 const tracked_objects::Location& from_here, Task* task) {
238 PostTask_Helper(from_here, task, 0, true);
239 }
240
241 void MessageLoop::PostDelayedTask(
b2ff702 Consistently use int64 for integers holding number of milliseconds.
phajdan.jr@chromium.org authored
242 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
243 PostTask_Helper(from_here, task, delay_ms, true);
244 }
245
246 void MessageLoop::PostNonNestableTask(
247 const tracked_objects::Location& from_here, Task* task) {
248 PostTask_Helper(from_here, task, 0, false);
249 }
250
251 void MessageLoop::PostNonNestableDelayedTask(
b2ff702 Consistently use int64 for integers holding number of milliseconds.
phajdan.jr@chromium.org authored
252 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
253 PostTask_Helper(from_here, task, delay_ms, false);
254 }
255
d7cae12 Add base to the repository.
initial.commit authored
256 // Possibly called on a background thread!
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
257 void MessageLoop::PostTask_Helper(
b2ff702 Consistently use int64 for integers holding number of milliseconds.
phajdan.jr@chromium.org authored
258 const tracked_objects::Location& from_here, Task* task, int64 delay_ms,
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
259 bool nestable) {
d7cae12 Add base to the repository.
initial.commit authored
260 task->SetBirthPlace(from_here);
6debf90 Switch SharedTimerWin over to using PostDelayedTask. I made some tweaks...
darin@google.com authored
261
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
262 PendingTask pending_task(task, nestable);
6debf90 Switch SharedTimerWin over to using PostDelayedTask. I made some tweaks...
darin@google.com authored
263
264 if (delay_ms > 0) {
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
265 pending_task.delayed_run_time =
6debf90 Switch SharedTimerWin over to using PostDelayedTask. I made some tweaks...
darin@google.com authored
266 Time::Now() + TimeDelta::FromMilliseconds(delay_ms);
267 } else {
36021ad Cleanup histogram classes mixing SetFlags into FactoryGet arguments
jar@chromium.org authored
268 DCHECK_EQ(delay_ms, 0) << "delay should not be negative";
6debf90 Switch SharedTimerWin over to using PostDelayedTask. I made some tweaks...
darin@google.com authored
269 }
270
d7cae12 Add base to the repository.
initial.commit authored
271 // Warning: Don't try to short-circuit, and handle this thread's tasks more
272 // directly, as it could starve handling of foreign threads. Put every task
273 // into this queue.
274
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
275 scoped_refptr<base::MessagePump> pump;
d7cae12 Add base to the repository.
initial.commit authored
276 {
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
277 AutoLock locked(incoming_queue_lock_);
278
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
279 bool was_empty = incoming_queue_.empty();
280 incoming_queue_.push(pending_task);
d7cae12 Add base to the repository.
initial.commit authored
281 if (!was_empty)
282 return; // Someone else should have started the sub-pump.
283
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
284 pump = pump_;
d7cae12 Add base to the repository.
initial.commit authored
285 }
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
286 // Since the incoming_queue_ may contain a task that destroys this message
287 // loop, we cannot exit incoming_queue_lock_ until we are done with |this|.
288 // We use a stack-based reference to the message pump so that we can call
289 // ScheduleWork outside of incoming_queue_lock_.
44f6598 rollback portions of r928 to test to see if it impacts perf
darin@google.com authored
290
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
291 pump->ScheduleWork();
d7cae12 Add base to the repository.
initial.commit authored
292 }
293
294 void MessageLoop::SetNestableTasksAllowed(bool allowed) {
aa98d73 Fix bug 1317458: Busy wait in IPC::SyncChannel::Send in some cases
mpcomplete@google.com authored
295 if (nestable_tasks_allowed_ != allowed) {
296 nestable_tasks_allowed_ = allowed;
297 if (!nestable_tasks_allowed_)
298 return;
299 // Start the native pump if we are not already pumping.
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
300 pump_->ScheduleWork();
aa98d73 Fix bug 1317458: Busy wait in IPC::SyncChannel::Send in some cases
mpcomplete@google.com authored
301 }
d7cae12 Add base to the repository.
initial.commit authored
302 }
303
304 bool MessageLoop::NestableTasksAllowed() const {
305 return nestable_tasks_allowed_;
306 }
307
df0de58 Adds time-out to browser-tests to prevent a hanging test from hanging th...
jcampan@chromium.org authored
308 bool MessageLoop::IsNested() {
309 return state_->run_depth > 1;
310 }
311
d7cae12 Add base to the repository.
initial.commit authored
312 //------------------------------------------------------------------------------
313
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
314 void MessageLoop::RunTask(Task* task) {
1b14c52 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@760 0039d316-1c4b-42...
darin@google.com authored
315 DCHECK(nestable_tasks_allowed_);
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
316 // Execute the task and assume the worst: It is probably not reentrant.
317 nestable_tasks_allowed_ = false;
d7cae12 Add base to the repository.
initial.commit authored
318
319 HistogramEvent(kTaskRunEvent);
320 task->Run();
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
321 delete task;
d7cae12 Add base to the repository.
initial.commit authored
322
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
323 nestable_tasks_allowed_ = true;
d7cae12 Add base to the repository.
initial.commit authored
324 }
325
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
326 bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) {
327 if (pending_task.nestable || state_->run_depth == 1) {
328 RunTask(pending_task.task);
329 // Show that we ran a task (Note: a new one might arrive as a
330 // consequence!).
331 return true;
332 }
333
334 // We couldn't run the task now because we're in a nested message loop
335 // and the task isn't nestable.
336 deferred_non_nestable_work_queue_.push(pending_task);
337 return false;
d7cae12 Add base to the repository.
initial.commit authored
338 }
339
5ffa1ca Put back r1891 with some task deletion disabled to maintain backwards co...
darin@chromium.org authored
340 void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) {
341 // Move to the delayed work queue. Initialize the sequence number
342 // before inserting into the delayed_work_queue_. The sequence number
343 // is used to faciliate FIFO sorting when two tasks have the same
344 // delayed_run_time value.
345 PendingTask new_pending_task(pending_task);
346 new_pending_task.sequence_num = next_sequence_num_++;
347 delayed_work_queue_.push(new_pending_task);
348 }
349
d7cae12 Add base to the repository.
initial.commit authored
350 void MessageLoop::ReloadWorkQueue() {
351 // We can improve performance of our loading tasks from incoming_queue_ to
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
352 // work_queue_ by waiting until the last minute (work_queue_ is empty) to
353 // load. That reduces the number of locks-per-task significantly when our
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
354 // queues get large.
355 if (!work_queue_.empty())
d7cae12 Add base to the repository.
initial.commit authored
356 return; // Wait till we *really* need to lock and load.
357
358 // Acquire all we can from the inter-thread queue with one lock acquisition.
359 {
360 AutoLock lock(incoming_queue_lock_);
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
361 if (incoming_queue_.empty())
d7cae12 Add base to the repository.
initial.commit authored
362 return;
5744a69 Make swapping the incoming queue with the work queue constant time.
darin@chromium.org authored
363 incoming_queue_.Swap(&work_queue_); // Constant time
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
364 DCHECK(incoming_queue_.empty());
d7cae12 Add base to the repository.
initial.commit authored
365 }
366 }
367
5ffa1ca Put back r1891 with some task deletion disabled to maintain backwards co...
darin@chromium.org authored
368 bool MessageLoop::DeletePendingTasks() {
369 bool did_work = !work_queue_.empty();
370 while (!work_queue_.empty()) {
371 PendingTask pending_task = work_queue_.front();
372 work_queue_.pop();
373 if (!pending_task.delayed_run_time.is_null()) {
374 // We want to delete delayed tasks in the same order in which they would
375 // normally be deleted in case of any funny dependencies between delayed
376 // tasks.
377 AddToDelayedWorkQueue(pending_task);
378 } else {
379 // TODO(darin): Delete all tasks once it is safe to do so.
d756fa2 During shutdown delete any pending tasks if running under Valgrind.
kuchhal@chromium.org authored
380 // Until it is totally safe, just do it when running Purify or
381 // Valgrind.
3b0ad67 Reapply r21429 - Cleanup pending tasks under Valgrind as well.
kuchhal@chromium.org authored
382 #if defined(PURIFY)
7e7fd58 (purify bustage) Correct purify (only) reference to variable
jar@chromium.org authored
383 delete pending_task.task;
d756fa2 During shutdown delete any pending tasks if running under Valgrind.
kuchhal@chromium.org authored
384 #elif defined(OS_POSIX)
385 if (RUNNING_ON_VALGRIND)
386 delete pending_task.task;
387 #endif // defined(OS_POSIX)
5ffa1ca Put back r1891 with some task deletion disabled to maintain backwards co...
darin@chromium.org authored
388 }
0a27cdd Delete pending tasks that have not run. To do this properly, I found th...
darin@google.com authored
389 }
5ffa1ca Put back r1891 with some task deletion disabled to maintain backwards co...
darin@chromium.org authored
390 did_work |= !deferred_non_nestable_work_queue_.empty();
391 while (!deferred_non_nestable_work_queue_.empty()) {
3c9b0cb Avoid leaks at shutdown when running purify
jar@chromium.org authored
392 // TODO(darin): Delete all tasks once it is safe to do so.
3b0ad67 Reapply r21429 - Cleanup pending tasks under Valgrind as well.
kuchhal@chromium.org authored
393 // Until it is totaly safe, only delete them under Purify and Valgrind.
394 Task* task = NULL;
395 #if defined(PURIFY)
396 task = deferred_non_nestable_work_queue_.front().task;
397 #elif defined(OS_POSIX)
398 if (RUNNING_ON_VALGRIND)
399 task = deferred_non_nestable_work_queue_.front().task;
6383feb Fix tree bustage
jar@chromium.org authored
400 #endif
401 deferred_non_nestable_work_queue_.pop();
3b0ad67 Reapply r21429 - Cleanup pending tasks under Valgrind as well.
kuchhal@chromium.org authored
402 if (task)
403 delete task;
5ffa1ca Put back r1891 with some task deletion disabled to maintain backwards co...
darin@chromium.org authored
404 }
405 did_work |= !delayed_work_queue_.empty();
406 while (!delayed_work_queue_.empty()) {
407 Task* task = delayed_work_queue_.top().task;
408 delayed_work_queue_.pop();
409 delete task;
d7cae12 Add base to the repository.
initial.commit authored
410 }
5ffa1ca Put back r1891 with some task deletion disabled to maintain backwards co...
darin@chromium.org authored
411 return did_work;
d7cae12 Add base to the repository.
initial.commit authored
412 }
413
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
414 bool MessageLoop::DoWork() {
415 if (!nestable_tasks_allowed_) {
416 // Task can't be executed right now.
417 return false;
418 }
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
419
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
420 for (;;) {
421 ReloadWorkQueue();
422 if (work_queue_.empty())
423 break;
424
425 // Execute oldest task.
426 do {
427 PendingTask pending_task = work_queue_.front();
428 work_queue_.pop();
429 if (!pending_task.delayed_run_time.is_null()) {
5ffa1ca Put back r1891 with some task deletion disabled to maintain backwards co...
darin@chromium.org authored
430 AddToDelayedWorkQueue(pending_task);
54696b3 Always use the topmost delayed task as the basis for our WM_TIMER.
darin@chromium.org authored
431 // If we changed the topmost task, then it is time to re-schedule.
432 if (delayed_work_queue_.top().task == pending_task.task)
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
433 pump_->ScheduleDelayedWork(pending_task.delayed_run_time);
434 } else {
435 if (DeferOrRunPendingTask(pending_task))
436 return true;
437 }
438 } while (!work_queue_.empty());
439 }
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
440
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
441 // Nothing happened.
442 return false;
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
443 }
444
e35950c reland r1075 w/ tweak to fix test failures
darin@google.com authored
445 bool MessageLoop::DoDelayedWork(Time* next_delayed_work_time) {
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
446 if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) {
447 *next_delayed_work_time = Time();
448 return false;
449 }
b3298a6 Add FD watching support to message_pump_libevent.
jeremy@chromium.org authored
450
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
451 if (delayed_work_queue_.top().delayed_run_time > Time::Now()) {
452 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
453 return false;
454 }
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
455
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
456 PendingTask pending_task = delayed_work_queue_.top();
457 delayed_work_queue_.pop();
b3298a6 Add FD watching support to message_pump_libevent.
jeremy@chromium.org authored
458
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
459 if (!delayed_work_queue_.empty())
460 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
461
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
462 return DeferOrRunPendingTask(pending_task);
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
463 }
464
465 bool MessageLoop::DoIdleWork() {
466 if (ProcessNextDelayedNonNestableTask())
467 return true;
468
469 if (state_->quit_received)
470 pump_->Quit();
471
472 return false;
473 }
474
475 //------------------------------------------------------------------------------
476 // MessageLoop::AutoRunState
477
478 MessageLoop::AutoRunState::AutoRunState(MessageLoop* loop) : loop_(loop) {
479 // Make the loop reference us.
480 previous_state_ = loop_->state_;
481 if (previous_state_) {
482 run_depth = previous_state_->run_depth + 1;
1b14c52 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@760 0039d316-1c4b-42...
darin@google.com authored
483 } else {
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
484 run_depth = 1;
1b14c52 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@760 0039d316-1c4b-42...
darin@google.com authored
485 }
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
486 loop_->state_ = this;
487
488 // Initialize the other fields:
489 quit_received = false;
b981968 Changes to base/ from a combination of FreeBSD and OpenBSD patches.
evan@chromium.org authored
490 #if !defined(OS_MACOSX)
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
491 dispatcher = NULL;
492 #endif
493 }
494
495 MessageLoop::AutoRunState::~AutoRunState() {
496 loop_->state_ = previous_state_;
1b14c52 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@760 0039d316-1c4b-42...
darin@google.com authored
497 }
498
d7cae12 Add base to the repository.
initial.commit authored
499 //------------------------------------------------------------------------------
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
500 // MessageLoop::PendingTask
d7cae12 Add base to the repository.
initial.commit authored
501
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
502 bool MessageLoop::PendingTask::operator<(const PendingTask& other) const {
503 // Since the top of a priority queue is defined as the "greatest" element, we
504 // need to invert the comparison here. We want the smaller time to be at the
505 // top of the heap.
d7cae12 Add base to the repository.
initial.commit authored
506
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
507 if (delayed_run_time < other.delayed_run_time)
508 return false;
d7cae12 Add base to the repository.
initial.commit authored
509
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
510 if (delayed_run_time > other.delayed_run_time)
511 return true;
d7cae12 Add base to the repository.
initial.commit authored
512
e9d2fa2 Eliminate the TimerManager by pulling its priority queue into MessageLoo...
darin@google.com authored
513 // If the times happen to match, then we use the sequence number to decide.
514 // Compare the difference to support integer roll-over.
515 return (sequence_num - other.sequence_num) > 0;
d7cae12 Add base to the repository.
initial.commit authored
516 }
517
518 //------------------------------------------------------------------------------
519 // Method and data for histogramming events and actions taken by each instance
520 // on each thread.
521
522 // static
523 bool MessageLoop::enable_histogrammer_ = false;
524
525 // static
526 void MessageLoop::EnableHistogrammer(bool enable) {
527 enable_histogrammer_ = enable;
528 }
529
530 void MessageLoop::StartHistogrammer() {
531 if (enable_histogrammer_ && !message_histogram_.get()
532 && StatisticsRecorder::WasStarted()) {
e188ff4 Take 2 at the new MessageLoop implementation.
darin@google.com authored
533 DCHECK(!thread_name_.empty());
36021ad Cleanup histogram classes mixing SetFlags into FactoryGet arguments
jar@chromium.org authored
534 message_histogram_ = LinearHistogram::FactoryGet("MsgLoop:" + thread_name_,
535 kLeastNonZeroMessageId, kMaxMessageId,
536 kNumberOfDistinctMessagesDisplayed,
537 message_histogram_->kHexRangePrintingFlag);
d7cae12 Add base to the repository.
initial.commit authored
538 message_histogram_->SetRangeDescriptions(event_descriptions_);
539 }
540 }
541
542 void MessageLoop::HistogramEvent(int event) {
543 if (message_histogram_.get())
544 message_histogram_->Add(event);
545 }
546
547 // Provide a macro that takes an expression (such as a constant, or macro
548 // constant) and creates a pair to initalize an array of pairs. In this case,
549 // our pair consists of the expressions value, and the "stringized" version
550 // of the expression (i.e., the exrpression put in quotes). For example, if
551 // we have:
552 // #define FOO 2
553 // #define BAR 5
554 // then the following:
555 // VALUE_TO_NUMBER_AND_NAME(FOO + BAR)
556 // will expand to:
557 // {7, "FOO + BAR"}
558 // We use the resulting array as an argument to our histogram, which reads the
559 // number as a bucket identifier, and proceeds to use the corresponding name
560 // in the pair (i.e., the quoted string) when printing out a histogram.
561 #define VALUE_TO_NUMBER_AND_NAME(name) {name, #name},
562
563 // static
564 const LinearHistogram::DescriptionPair MessageLoop::event_descriptions_[] = {
565 // Provide some pretty print capability in our histogram for our internal
566 // messages.
567
568 // A few events we handle (kindred to messages), and used to profile actions.
569 VALUE_TO_NUMBER_AND_NAME(kTaskRunEvent)
570 VALUE_TO_NUMBER_AND_NAME(kTimerEvent)
571
572 {-1, NULL} // The list must be null terminated, per API to histogram.
573 };
1457f56 Use a more compact license header in source files.
license.bot authored
574
5da457d Allow consumers of MessageLoop to specify the type of MessageLoop they w...
darin@google.com authored
575 //------------------------------------------------------------------------------
576 // MessageLoopForUI
577
4cbc26c This CL adds accelerators to the Linux toolkit views.
jcampan@chromium.org authored
578 #if defined(OS_WIN)
579 void MessageLoopForUI::WillProcessMessage(const MSG& message) {
580 pump_win()->WillProcessMessage(message);
581 }
582 void MessageLoopForUI::DidProcessMessage(const MSG& message) {
583 pump_win()->DidProcessMessage(message);
584 }
585 void MessageLoopForUI::PumpOutPendingPaintMessages() {
586 pump_ui()->PumpOutPendingPaintMessages();
587 }
588
589 #endif // defined(OS_WIN)
d095589 Promotes Add/RemoveObserver to MessageLoop for linux. Because
sky@chromium.org authored
590
b981968 Changes to base/ from a combination of FreeBSD and OpenBSD patches.
evan@chromium.org authored
591 #if !defined(OS_MACOSX)
d095589 Promotes Add/RemoveObserver to MessageLoop for linux. Because
sky@chromium.org authored
592 void MessageLoopForUI::AddObserver(Observer* observer) {
593 pump_ui()->AddObserver(observer);
594 }
595
596 void MessageLoopForUI::RemoveObserver(Observer* observer) {
597 pump_ui()->RemoveObserver(observer);
598 }
599
5da457d Allow consumers of MessageLoop to specify the type of MessageLoop they w...
darin@google.com authored
600 void MessageLoopForUI::Run(Dispatcher* dispatcher) {
601 AutoRunState save_state(this);
602 state_->dispatcher = dispatcher;
603 RunHandler();
604 }
b981968 Changes to base/ from a combination of FreeBSD and OpenBSD patches.
evan@chromium.org authored
605 #endif // !defined(OS_MACOSX)
5da457d Allow consumers of MessageLoop to specify the type of MessageLoop they w...
darin@google.com authored
606
607 //------------------------------------------------------------------------------
608 // MessageLoopForIO
609
610 #if defined(OS_WIN)
611
d429e5d Add a way to register for completion-ports based async operations to be ...
rvargas@google.com authored
612 void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) {
613 pump_io()->RegisterIOHandler(file, handler);
614 }
615
09d8d1c Switch MessagePumpForIO to use completion ports on Windows.
rvargas@google.com authored
616 bool MessageLoopForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) {
617 return pump_io()->WaitForIOCompletion(timeout, filter);
d429e5d Add a way to register for completion-ports based async operations to be ...
rvargas@google.com authored
618 }
619
33e4111 Use libevent, second try. Changes this time:
dkegel@google.com authored
620 #elif defined(OS_POSIX)
621
bd8a0e9 message_pump_libevent refactor:
jeremy@chromium.org authored
622 bool MessageLoopForIO::WatchFileDescriptor(int fd,
623 bool persistent,
624 Mode mode,
625 FileDescriptorWatcher *controller,
626 Watcher *delegate) {
627 return pump_libevent()->WatchFileDescriptor(
628 fd,
629 persistent,
630 static_cast<base::MessagePumpLibevent::Mode>(mode),
631 controller,
632 delegate);
33e4111 Use libevent, second try. Changes this time:
dkegel@google.com authored
633 }
634
635 #endif
Something went wrong with that request. Please try again.