blob: d014bc13b1f70b469925719a602011e0834b1739 [file] [log] [blame]
license.botf003cfe2008-08-24 09:55:55 +09001// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit3f4a7322008-07-27 06:49:38 +09004
darin@google.com981f3552008-08-16 12:09:05 +09005#ifndef BASE_MESSAGE_LOOP_H_
6#define BASE_MESSAGE_LOOP_H_
initial.commit3f4a7322008-07-27 06:49:38 +09007
initial.commit3f4a7322008-07-27 06:49:38 +09008#include <deque>
9#include <queue>
10#include <string>
11#include <vector>
12
13#include "base/histogram.h"
darin@google.com981f3552008-08-16 12:09:05 +090014#include "base/message_pump.h"
initial.commit3f4a7322008-07-27 06:49:38 +090015#include "base/observer_list.h"
darin@google.com981f3552008-08-16 12:09:05 +090016#include "base/ref_counted.h"
initial.commit3f4a7322008-07-27 06:49:38 +090017#include "base/task.h"
18#include "base/timer.h"
19#include "base/thread_local_storage.h"
20
darin@google.com981f3552008-08-16 12:09:05 +090021#if defined(OS_WIN)
22// We need this to declare base::MessagePumpWin::Dispatcher, which we should
23// really just eliminate.
24#include "base/message_pump_win.h"
25#endif
darin@google.com6ddeb842008-08-15 16:31:20 +090026
darin@google.com981f3552008-08-16 12:09:05 +090027// A MessageLoop is used to process events for a particular thread. There is
28// at most one MessageLoop instance per thread.
29//
30// Events include at a minimum Task instances submitted to PostTask or those
31// managed by TimerManager. Depending on the type of message pump used by the
32// MessageLoop other events such as UI messages may be processed. On Windows
33// APC calls (as time permits) and signals sent to a registered set of HANDLEs
34// may also be processed.
initial.commit3f4a7322008-07-27 06:49:38 +090035//
36// NOTE: Unless otherwise specified, a MessageLoop's methods may only be called
37// on the thread where the MessageLoop's Run method executes.
38//
darin@google.com981f3552008-08-16 12:09:05 +090039// NOTE: MessageLoop has task reentrancy protection. This means that if a
initial.commit3f4a7322008-07-27 06:49:38 +090040// task is being processed, a second task cannot start until the first task is
darin@google.com981f3552008-08-16 12:09:05 +090041// finished. Reentrancy can happen when processing a task, and an inner
42// message pump is created. That inner pump then processes native messages
43// which could implicitly start an inner task. Inner message pumps are created
44// with dialogs (DialogBox), common dialogs (GetOpenFileName), OLE functions
45// (DoDragDrop), printer functions (StartDoc) and *many* others.
46//
initial.commit3f4a7322008-07-27 06:49:38 +090047// Sample workaround when inner task processing is needed:
48// bool old_state = MessageLoop::current()->NestableTasksAllowed();
49// MessageLoop::current()->SetNestableTasksAllowed(true);
50// HRESULT hr = DoDragDrop(...); // Implicitly runs a modal message loop here.
51// MessageLoop::current()->SetNestableTasksAllowed(old_state);
52// // Process hr (the result returned by DoDragDrop().
53//
darin@google.com981f3552008-08-16 12:09:05 +090054// Please be SURE your task is reentrant (nestable) and all global variables
55// are stable and accessible before calling SetNestableTasksAllowed(true).
initial.commit3f4a7322008-07-27 06:49:38 +090056//
darin@google.com981f3552008-08-16 12:09:05 +090057class MessageLoop : public base::MessagePump::Delegate {
initial.commit3f4a7322008-07-27 06:49:38 +090058 public:
initial.commit3f4a7322008-07-27 06:49:38 +090059 static void EnableHistogrammer(bool enable_histogrammer);
60
darin@google.com38100322008-08-07 06:27:02 +090061 // A DestructionObserver is notified when the current MessageLoop is being
62 // destroyed. These obsevers are notified prior to MessageLoop::current()
63 // being changed to return NULL. This gives interested parties the chance to
64 // do final cleanup that depends on the MessageLoop.
65 //
66 // NOTE: Any tasks posted to the MessageLoop during this notification will
67 // not be run. Instead, they will be deleted.
68 //
69 class DestructionObserver {
70 public:
71 virtual ~DestructionObserver() {}
72 virtual void WillDestroyCurrentMessageLoop() = 0;
73 };
74
75 // Add a DestructionObserver, which will start receiving notifications
76 // immediately.
77 void AddDestructionObserver(DestructionObserver* destruction_observer);
78
79 // Remove a DestructionObserver. It is safe to call this method while a
80 // DestructionObserver is receiving a notification callback.
81 void RemoveDestructionObserver(DestructionObserver* destruction_observer);
82
initial.commit3f4a7322008-07-27 06:49:38 +090083 // Call the task's Run method asynchronously from within a message loop at
84 // some point in the future. With the PostTask variant, tasks are invoked in
85 // FIFO order, inter-mixed with normal UI event processing. With the
86 // PostDelayedTask variant, tasks are called after at least approximately
87 // 'delay_ms' have elapsed.
88 //
89 // The MessageLoop takes ownership of the Task, and deletes it after it
90 // has been Run().
91 //
92 // NOTE: This method may be called on any thread. The Task will be invoked
93 // on the thread that executes MessageLoop::Run().
94
95 void PostTask(const tracked_objects::Location& from_here, Task* task) {
96 PostDelayedTask(from_here, task, 0);
97 }
98
99 void PostDelayedTask(const tracked_objects::Location& from_here, Task* task,
100 int delay_ms);
101
102 // A variant on PostTask that deletes the given object. This is useful
103 // if the object needs to live until the next run of the MessageLoop (for
104 // example, deleting a RenderProcessHost from within an IPC callback is not
105 // good).
106 //
107 // NOTE: This method may be called on any thread. The object will be deleted
108 // on the thread that executes MessageLoop::Run(). If this is not the same
109 // as the thread that calls PostDelayedTask(FROM_HERE, ), then T MUST inherit
110 // from RefCountedThreadSafe<T>!
111 template <class T>
112 void DeleteSoon(const tracked_objects::Location& from_here, T* object) {
113 PostTask(from_here, new DeleteTask<T>(object));
114 }
115
116 // A variant on PostTask that releases the given reference counted object
117 // (by calling its Release method). This is useful if the object needs to
118 // live until the next run of the MessageLoop, or if the object needs to be
119 // released on a particular thread.
120 //
121 // NOTE: This method may be called on any thread. The object will be
122 // released (and thus possibly deleted) on the thread that executes
123 // MessageLoop::Run(). If this is not the same as the thread that calls
124 // PostDelayedTask(FROM_HERE, ), then T MUST inherit from
125 // RefCountedThreadSafe<T>!
126 template <class T>
127 void ReleaseSoon(const tracked_objects::Location& from_here, T* object) {
128 PostTask(from_here, new ReleaseTask<T>(object));
129 }
130
jar@google.comb4d1bff2008-07-31 04:03:59 +0900131 // Run the message loop.
initial.commit3f4a7322008-07-27 06:49:38 +0900132 void Run();
133
jar@google.com9239e022008-07-31 22:10:20 +0900134 // Process all pending tasks, windows messages, etc., but don't wait/sleep.
135 // Return as soon as all items that can be run are taken care of.
136 void RunAllPending();
jar@google.comb4d1bff2008-07-31 04:03:59 +0900137
initial.commit3f4a7322008-07-27 06:49:38 +0900138 // Signals the Run method to return after it is done processing all pending
darin@google.com981f3552008-08-16 12:09:05 +0900139 // messages. This method may only be called on the same thread that called
140 // Run, and Run must still be on the call stack.
initial.commit3f4a7322008-07-27 06:49:38 +0900141 //
darin@google.com981f3552008-08-16 12:09:05 +0900142 // Use QuitTask if you need to Quit another thread's MessageLoop, but note
143 // that doing so is fairly dangerous if the target thread makes nested calls
144 // to MessageLoop::Run. The problem being that you won't know which nested
145 // run loop you are quiting, so be careful!
146 //
initial.commit3f4a7322008-07-27 06:49:38 +0900147 void Quit();
148
darin@google.com981f3552008-08-16 12:09:05 +0900149 // Invokes Quit on the current MessageLoop when run. Useful to schedule an
initial.commit3f4a7322008-07-27 06:49:38 +0900150 // arbitrary MessageLoop to Quit.
151 class QuitTask : public Task {
152 public:
153 virtual void Run() {
154 MessageLoop::current()->Quit();
155 }
156 };
157
initial.commit3f4a7322008-07-27 06:49:38 +0900158 // Normally, it is not necessary to instantiate a MessageLoop. Instead, it
159 // is typical to make use of the current thread's MessageLoop instance.
160 MessageLoop();
161 ~MessageLoop();
162
163 // Optional call to connect the thread name with this loop.
darin@google.com981f3552008-08-16 12:09:05 +0900164 void set_thread_name(const std::string& thread_name) {
165 DCHECK(thread_name_.empty()) << "Should not rename this thread!";
166 thread_name_ = thread_name;
167 }
darin@google.com38100322008-08-07 06:27:02 +0900168 const std::string& thread_name() const { return thread_name_; }
initial.commit3f4a7322008-07-27 06:49:38 +0900169
170 // Returns the MessageLoop object for the current thread, or null if none.
171 static MessageLoop* current() {
evanm@google.comf26fd3a2008-08-21 07:54:52 +0900172 return static_cast<MessageLoop*>(tls_index_.Get());
initial.commit3f4a7322008-07-27 06:49:38 +0900173 }
174
175 // Returns the TimerManager object for the current thread.
176 TimerManager* timer_manager() { return &timer_manager_; }
177
initial.commit3f4a7322008-07-27 06:49:38 +0900178 // Enables or disables the recursive task processing. This happens in the case
179 // of recursive message loops. Some unwanted message loop may occurs when
180 // using common controls or printer functions. By default, recursive task
181 // processing is disabled.
182 //
183 // The specific case where tasks get queued is:
184 // - The thread is running a message loop.
185 // - It receives a task #1 and execute it.
186 // - The task #1 implicitly start a message loop, like a MessageBox in the
187 // unit test. This can also be StartDoc or GetSaveFileName.
188 // - The thread receives a task #2 before or while in this second message
189 // loop.
190 // - With NestableTasksAllowed set to true, the task #2 will run right away.
191 // Otherwise, it will get executed right after task #1 completes at "thread
192 // message loop level".
193 void SetNestableTasksAllowed(bool allowed);
194 bool NestableTasksAllowed() const;
195
196 // Enables or disables the restoration during an exception of the unhandled
197 // exception filter that was active when Run() was called. This can happen
198 // if some third party code call SetUnhandledExceptionFilter() and never
199 // restores the previous filter.
200 void set_exception_restoration(bool restore) {
201 exception_restoration_ = restore;
202 }
203
darin@google.com981f3552008-08-16 12:09:05 +0900204 //----------------------------------------------------------------------------
205#if defined(OS_WIN)
206 // Backwards-compat for the old Windows-specific MessageLoop API. These APIs
207 // are deprecated.
initial.commit3f4a7322008-07-27 06:49:38 +0900208
darin@google.com981f3552008-08-16 12:09:05 +0900209 typedef base::MessagePumpWin::Dispatcher Dispatcher;
210 typedef base::MessagePumpWin::Observer Observer;
211 typedef base::MessagePumpWin::Watcher Watcher;
initial.commit3f4a7322008-07-27 06:49:38 +0900212
darin@google.com981f3552008-08-16 12:09:05 +0900213 void Run(Dispatcher* dispatcher);
214
215 void WatchObject(HANDLE object, Watcher* watcher) {
216 pump_win()->WatchObject(object, watcher);
217 }
218 void AddObserver(Observer* observer) {
219 pump_win()->AddObserver(observer);
220 }
221 void RemoveObserver(Observer* observer) {
222 pump_win()->RemoveObserver(observer);
223 }
224 void WillProcessMessage(const MSG& message) {
225 pump_win()->WillProcessMessage(message);
226 }
227 void DidProcessMessage(const MSG& message) {
228 pump_win()->DidProcessMessage(message);
229 }
230 void PumpOutPendingPaintMessages() {
231 pump_win()->PumpOutPendingPaintMessages();
232 }
233#endif // defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900234
235 //----------------------------------------------------------------------------
236 private:
darin@google.comee6fa722008-08-13 08:25:43 +0900237 friend class TimerManager; // So it can call DidChangeNextTimerExpiry
238
darin@google.com981f3552008-08-16 12:09:05 +0900239 struct RunState {
240 // Used to count how many Run() invocations are on the stack.
241 int run_depth;
initial.commit3f4a7322008-07-27 06:49:38 +0900242
darin@google.com981f3552008-08-16 12:09:05 +0900243 // Used to record that Quit() was called, or that we should quit the pump
244 // once it becomes idle.
245 bool quit_received;
initial.commit3f4a7322008-07-27 06:49:38 +0900246
darin@google.com981f3552008-08-16 12:09:05 +0900247#if defined(OS_WIN)
248 base::MessagePumpWin::Dispatcher* dispatcher;
249#endif
250 };
251
252 class AutoRunState : RunState {
253 public:
254 AutoRunState(MessageLoop* loop);
255 ~AutoRunState();
initial.commit3f4a7322008-07-27 06:49:38 +0900256 private:
257 MessageLoop* loop_;
darin@google.com981f3552008-08-16 12:09:05 +0900258 RunState* previous_state_;
259 };
initial.commit3f4a7322008-07-27 06:49:38 +0900260
261 // A prioritized queue with interface that mostly matches std::queue<>.
262 // For debugging/performance testing, you can swap in std::queue<Task*>.
263 class PrioritizedTaskQueue {
264 public:
265 PrioritizedTaskQueue() : next_sequence_number_(0) {}
266 ~PrioritizedTaskQueue() {}
267 void pop() { queue_.pop(); }
268 bool empty() { return queue_.empty(); }
269 size_t size() { return queue_.size(); }
270 Task* front() { return queue_.top().task(); }
271 void push(Task * task);
272
273 private:
274 class PrioritizedTask {
275 public:
276 PrioritizedTask(Task* task, int sequence_number)
277 : task_(task),
278 sequence_number_(sequence_number),
279 priority_(task->priority()) {}
darin@google.com38100322008-08-07 06:27:02 +0900280 Task* task() const { return task_; }
initial.commit3f4a7322008-07-27 06:49:38 +0900281 bool operator < (PrioritizedTask const & right) const ;
282
283 private:
284 Task* task_;
285 // Number to ensure (default) FIFO ordering in a PriorityQueue.
286 int sequence_number_;
287 // Priority of task when pushed.
288 int priority_;
289 }; // class PrioritizedTask
290
291 std::priority_queue<PrioritizedTask> queue_;
292 // Default sequence number used when push'ing (monotonically decreasing).
293 int next_sequence_number_;
294 DISALLOW_EVIL_CONSTRUCTORS(PrioritizedTaskQueue);
295 };
296
297 // Implementation of a TaskQueue as a null terminated list, with end pointers.
298 class TaskQueue {
299 public:
300 TaskQueue() : first_(NULL), last_(NULL) {}
301 void Push(Task* task);
302 Task* Pop(); // Extract the next Task from the queue, and return it.
303 bool Empty() const { return !first_; }
initial.commit3f4a7322008-07-27 06:49:38 +0900304 private:
305 Task* first_;
306 Task* last_;
307 };
308
309 // Implementation of a Task queue that automatically switches into a priority
310 // queue if it observes any non-zero priorities in tasks.
311 class OptionallyPrioritizedTaskQueue {
312 public:
313 OptionallyPrioritizedTaskQueue() : use_priority_queue_(false) {}
314 void Push(Task* task);
315 Task* Pop(); // Extract next Task from queue, and return it.
316 bool Empty();
317 bool use_priority_queue() const { return use_priority_queue_; }
318
319 private:
320 bool use_priority_queue_;
321 PrioritizedTaskQueue prioritized_queue_;
322 TaskQueue queue_;
323 DISALLOW_EVIL_CONSTRUCTORS(OptionallyPrioritizedTaskQueue);
324 };
325
darin@google.com981f3552008-08-16 12:09:05 +0900326#if defined(OS_WIN)
327 base::MessagePumpWin* pump_win() {
328 return static_cast<base::MessagePumpWin*>(pump_.get());
329 }
330#endif
jar@google.comb4d1bff2008-07-31 04:03:59 +0900331
332 // A function to encapsulate all the exception handling capability in the
darin@google.com981f3552008-08-16 12:09:05 +0900333 // stacks around the running of a main message loop. It will run the message
334 // loop in a SEH try block or not depending on the set_SEH_restoration()
335 // flag.
336 void RunHandler();
initial.commit3f4a7322008-07-27 06:49:38 +0900337
jar@google.comb4d1bff2008-07-31 04:03:59 +0900338 // A surrounding stack frame around the running of the message loop that
339 // supports all saving and restoring of state, as is needed for any/all (ugly)
340 // recursive calls.
darin@google.com981f3552008-08-16 12:09:05 +0900341 void RunInternal();
darin@google.com6ddeb842008-08-15 16:31:20 +0900342
darin@google.com981f3552008-08-16 12:09:05 +0900343 // Called to process any delayed non-nestable tasks.
initial.commit3f4a7322008-07-27 06:49:38 +0900344 bool ProcessNextDelayedNonNestableTask();
initial.commit3f4a7322008-07-27 06:49:38 +0900345
346 //----------------------------------------------------------------------------
initial.commit3f4a7322008-07-27 06:49:38 +0900347 // Run a work_queue_ task or new_task, and delete it (if it was processed by
348 // PostTask). If there are queued tasks, the oldest one is executed and
349 // new_task is queued. new_task is optional and can be NULL. In this NULL
350 // case, the method will run one pending task (if any exist). Returns true if
darin@google.com981f3552008-08-16 12:09:05 +0900351 // it executes a task. Queued tasks accumulate only when there is a
352 // non-nestable task currently processing, in which case the new_task is
353 // appended to the list work_queue_. Such re-entrancy generally happens when
354 // an unrequested message pump (typical of a native dialog) is executing in
355 // the context of a task.
initial.commit3f4a7322008-07-27 06:49:38 +0900356 bool QueueOrRunTask(Task* new_task);
357
358 // Runs the specified task and deletes it.
359 void RunTask(Task* task);
360
361 // Make state adjustments just before and after running tasks so that we can
362 // continue to work if a native message loop is employed during a task.
363 void BeforeTaskRunSetup();
364 void AfterTaskRunRestore();
365
initial.commit3f4a7322008-07-27 06:49:38 +0900366 // Load tasks from the incoming_queue_ into work_queue_ if the latter is
367 // empty. The former requires a lock to access, while the latter is directly
368 // accessible on this thread.
369 void ReloadWorkQueue();
370
371 // Delete tasks that haven't run yet without running them. Used in the
372 // destructor to make sure all the task's destructors get called.
373 void DeletePendingTasks();
374
initial.commit3f4a7322008-07-27 06:49:38 +0900375 // Post a task to our incomming queue.
darin@google.com38100322008-08-07 06:27:02 +0900376 void PostTaskInternal(Task* task);
initial.commit3f4a7322008-07-27 06:49:38 +0900377
darin@google.comee6fa722008-08-13 08:25:43 +0900378 // Called by the TimerManager when its next timer changes.
379 void DidChangeNextTimerExpiry();
380
darin@google.com981f3552008-08-16 12:09:05 +0900381 // Entry point for TimerManager to request the Run() of a task. If we
382 // created the task during an PostTask(FROM_HERE, ), then we will also
383 // perform destructions, and we'll have the option of queueing the task. If
384 // we didn't create the timer, then we will Run it immediately.
385 bool RunTimerTask(Timer* timer);
386
387 // Since some Timer's are owned by MessageLoop, the TimerManager (when it is
388 // being destructed) passses us the timers to discard (without doing a Run()).
389 void DiscardTimer(Timer* timer);
390
391 // base::MessagePump::Delegate methods:
392 virtual bool DoWork();
darin@google.com6393bed2008-08-20 15:30:58 +0900393 virtual bool DoDelayedWork(Time* next_delayed_work_time);
darin@google.com981f3552008-08-16 12:09:05 +0900394 virtual bool DoIdleWork();
395
initial.commit3f4a7322008-07-27 06:49:38 +0900396 // Start recording histogram info about events and action IF it was enabled
397 // and IF the statistics recorder can accept a registration of our histogram.
398 void StartHistogrammer();
399
400 // Add occurence of event to our histogram, so that we can see what is being
401 // done in a specific MessageLoop instance (i.e., specific thread).
402 // If message_histogram_ is NULL, this is a no-op.
403 void HistogramEvent(int event);
404
405 static TLSSlot tls_index_;
initial.commit3f4a7322008-07-27 06:49:38 +0900406 static const LinearHistogram::DescriptionPair event_descriptions_[];
407 static bool enable_histogrammer_;
408
409 TimerManager timer_manager_;
410
411 // A list of tasks that need to be processed by this instance. Note that this
412 // queue is only accessed (push/pop) by our current thread.
413 // As an optimization, when we don't need to use the prioritization of
414 // work_queue_, we use a null terminated list (TaskQueue) as our
415 // implementation of the queue. This saves on memory (list uses pointers
416 // internal to Task) and probably runs faster than the priority queue when
417 // there was no real prioritization.
418 OptionallyPrioritizedTaskQueue work_queue_;
419
darin@google.com981f3552008-08-16 12:09:05 +0900420 scoped_refptr<base::MessagePump> pump_;
darin@google.com38100322008-08-07 06:27:02 +0900421
darin@google.com965e5342008-08-06 08:16:41 +0900422 ObserverList<DestructionObserver> destruction_observers_;
initial.commit3f4a7322008-07-27 06:49:38 +0900423 // A recursion block that prevents accidentally running additonal tasks when
424 // insider a (accidentally induced?) nested message pump.
425 bool nestable_tasks_allowed_;
426
427 bool exception_restoration_;
428
initial.commit3f4a7322008-07-27 06:49:38 +0900429 std::string thread_name_;
430 // A profiling histogram showing the counts of various messages and events.
431 scoped_ptr<LinearHistogram> message_histogram_;
432
433 // A null terminated list which creates an incoming_queue of tasks that are
434 // aquired under a mutex for processing on this instance's thread. These tasks
435 // have not yet been sorted out into items for our work_queue_ vs items that
436 // will be handled by the TimerManager.
437 TaskQueue incoming_queue_;
438 // Protect access to incoming_queue_.
439 Lock incoming_queue_lock_;
440
441 // A null terminated list of non-nestable tasks that we had to delay because
442 // when it came time to execute them we were in a nested message loop. They
443 // will execute once we're out of nested message loops.
444 TaskQueue delayed_non_nestable_queue_;
445
darin@google.com981f3552008-08-16 12:09:05 +0900446 RunState* state_;
initial.commit3f4a7322008-07-27 06:49:38 +0900447
darin@google.com981f3552008-08-16 12:09:05 +0900448 DISALLOW_COPY_AND_ASSIGN(MessageLoop);
initial.commit3f4a7322008-07-27 06:49:38 +0900449};
450
darin@google.com981f3552008-08-16 12:09:05 +0900451#endif // BASE_MESSAGE_LOOP_H_
license.botf003cfe2008-08-24 09:55:55 +0900452