Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
4 : // Use of this source code is governed by a BSD-style license that can be
5 : // found in the LICENSE file.
6 :
7 : #ifndef BASE_MESSAGE_LOOP_H_
8 : #define BASE_MESSAGE_LOOP_H_
9 :
10 : #include <deque>
11 : #include <queue>
12 : #include <string>
13 : #include <vector>
14 : #include <map>
15 :
16 : #include "base/lock.h"
17 : #include "base/message_pump.h"
18 : #include "base/observer_list.h"
19 :
20 : #if defined(OS_WIN)
21 : // We need this to declare base::MessagePumpWin::Dispatcher, which we should
22 : // really just eliminate.
23 : #include "base/message_pump_win.h"
24 : #elif defined(OS_POSIX)
25 : #include "base/message_pump_libevent.h"
26 : #endif
27 :
28 : #include "nsAutoPtr.h"
29 : #include "nsCOMPtr.h"
30 : #include "nsIRunnable.h"
31 : #include "nsThreadUtils.h"
32 :
33 : class nsISerialEventTarget;
34 : class nsIThread;
35 :
36 : namespace mozilla {
37 : namespace ipc {
38 :
39 : class DoWorkRunnable;
40 :
41 : } /* namespace ipc */
42 : } /* namespace mozilla */
43 :
44 : // A MessageLoop is used to process events for a particular thread. There is
45 : // at most one MessageLoop instance per thread.
46 : //
47 : // Events include at a minimum Task instances submitted to PostTask or those
48 : // managed by TimerManager. Depending on the type of message pump used by the
49 : // MessageLoop other events such as UI messages may be processed. On Windows
50 : // APC calls (as time permits) and signals sent to a registered set of HANDLEs
51 : // may also be processed.
52 : //
53 : // NOTE: Unless otherwise specified, a MessageLoop's methods may only be called
54 : // on the thread where the MessageLoop's Run method executes.
55 : //
56 : // NOTE: MessageLoop has task reentrancy protection. This means that if a
57 : // task is being processed, a second task cannot start until the first task is
58 : // finished. Reentrancy can happen when processing a task, and an inner
59 : // message pump is created. That inner pump then processes native messages
60 : // which could implicitly start an inner task. Inner message pumps are created
61 : // with dialogs (DialogBox), common dialogs (GetOpenFileName), OLE functions
62 : // (DoDragDrop), printer functions (StartDoc) and *many* others.
63 : //
64 : // Sample workaround when inner task processing is needed:
65 : // bool old_state = MessageLoop::current()->NestableTasksAllowed();
66 : // MessageLoop::current()->SetNestableTasksAllowed(true);
67 : // HRESULT hr = DoDragDrop(...); // Implicitly runs a modal message loop here.
68 : // MessageLoop::current()->SetNestableTasksAllowed(old_state);
69 : // // Process hr (the result returned by DoDragDrop().
70 : //
71 : // Please be SURE your task is reentrant (nestable) and all global variables
72 : // are stable and accessible before calling SetNestableTasksAllowed(true).
73 : //
74 : class MessageLoop : public base::MessagePump::Delegate {
75 :
76 : friend class mozilla::ipc::DoWorkRunnable;
77 :
78 : public:
79 : // A DestructionObserver is notified when the current MessageLoop is being
80 : // destroyed. These obsevers are notified prior to MessageLoop::current()
81 : // being changed to return NULL. This gives interested parties the chance to
82 : // do final cleanup that depends on the MessageLoop.
83 : //
84 : // NOTE: Any tasks posted to the MessageLoop during this notification will
85 : // not be run. Instead, they will be deleted.
86 : //
87 107 : class DestructionObserver {
88 : public:
89 1 : virtual ~DestructionObserver() {}
90 : virtual void WillDestroyCurrentMessageLoop() = 0;
91 : };
92 :
93 : // Add a DestructionObserver, which will start receiving notifications
94 : // immediately.
95 : void AddDestructionObserver(DestructionObserver* destruction_observer);
96 :
97 : // Remove a DestructionObserver. It is safe to call this method while a
98 : // DestructionObserver is receiving a notification callback.
99 : void RemoveDestructionObserver(DestructionObserver* destruction_observer);
100 :
101 : // The "PostTask" family of methods call the task's Run method asynchronously
102 : // from within a message loop at some point in the future.
103 : //
104 : // With the PostTask variant, tasks are invoked in FIFO order, inter-mixed
105 : // with normal UI or IO event processing. With the PostDelayedTask variant,
106 : // tasks are called after at least approximately 'delay_ms' have elapsed.
107 : //
108 : // The NonNestable variants work similarly except that they promise never to
109 : // dispatch the task from a nested invocation of MessageLoop::Run. Instead,
110 : // such tasks get deferred until the top-most MessageLoop::Run is executing.
111 : //
112 : // The MessageLoop takes ownership of the Task, and deletes it after it has
113 : // been Run().
114 : //
115 : // NOTE: These methods may be called on any thread. The Task will be invoked
116 : // on the thread that executes MessageLoop::Run().
117 :
118 : void PostTask(already_AddRefed<nsIRunnable> task);
119 :
120 : void PostDelayedTask(already_AddRefed<nsIRunnable> task, int delay_ms);
121 :
122 : // PostIdleTask is not thread safe and should be called on this thread
123 : void PostIdleTask(already_AddRefed<nsIRunnable> task);
124 :
125 : // Run the message loop.
126 : void Run();
127 :
128 : // Signals the Run method to return after it is done processing all pending
129 : // messages. This method may only be called on the same thread that called
130 : // Run, and Run must still be on the call stack.
131 : //
132 : // Use QuitTask if you need to Quit another thread's MessageLoop, but note
133 : // that doing so is fairly dangerous if the target thread makes nested calls
134 : // to MessageLoop::Run. The problem being that you won't know which nested
135 : // run loop you are quiting, so be careful!
136 : //
137 : void Quit();
138 :
139 : // Invokes Quit on the current MessageLoop when run. Useful to schedule an
140 : // arbitrary MessageLoop to Quit.
141 0 : class QuitTask : public mozilla::Runnable {
142 : public:
143 0 : QuitTask() : mozilla::Runnable("QuitTask") {}
144 0 : NS_IMETHOD Run() override {
145 0 : MessageLoop::current()->Quit();
146 0 : return NS_OK;
147 : }
148 : };
149 :
150 : // Return an XPCOM-compatible event target for this thread.
151 : nsISerialEventTarget* SerialEventTarget();
152 :
153 : // A MessageLoop has a particular type, which indicates the set of
154 : // asynchronous events it may process in addition to tasks and timers.
155 : //
156 : // TYPE_DEFAULT
157 : // This type of ML only supports tasks and timers.
158 : //
159 : // TYPE_UI
160 : // This type of ML also supports native UI events (e.g., Windows messages).
161 : // See also MessageLoopForUI.
162 : //
163 : // TYPE_IO
164 : // This type of ML also supports asynchronous IO. See also
165 : // MessageLoopForIO.
166 : //
167 : // TYPE_MOZILLA_CHILD
168 : // This type of ML is used in Mozilla child processes which initialize
169 : // XPCOM and use the gecko event loop.
170 : //
171 : // TYPE_MOZILLA_PARENT
172 : // This type of ML is used in Mozilla parent processes which initialize
173 : // XPCOM and use the gecko event loop.
174 : //
175 : // TYPE_MOZILLA_NONMAINTHREAD
176 : // This type of ML is used in Mozilla parent processes which initialize
177 : // XPCOM and use the nsThread event loop.
178 : //
179 : // TYPE_MOZILLA_NONMAINUITHREAD
180 : // This type of ML is used in Mozilla processes which initialize XPCOM
181 : // and use TYPE_UI loop logic.
182 : //
183 : enum Type {
184 : TYPE_DEFAULT,
185 : TYPE_UI,
186 : TYPE_IO,
187 : TYPE_MOZILLA_CHILD,
188 : TYPE_MOZILLA_PARENT,
189 : TYPE_MOZILLA_NONMAINTHREAD,
190 : TYPE_MOZILLA_NONMAINUITHREAD,
191 : TYPE_MOZILLA_ANDROID_UI
192 : };
193 :
194 : // Normally, it is not necessary to instantiate a MessageLoop. Instead, it
195 : // is typical to make use of the current thread's MessageLoop instance.
196 : explicit MessageLoop(Type type = TYPE_DEFAULT, nsIThread* aThread = nullptr);
197 : ~MessageLoop();
198 :
199 : // Returns the type passed to the constructor.
200 47 : Type type() const { return type_; }
201 :
202 : // Unique, non-repeating ID for this message loop.
203 0 : int32_t id() const { return id_; }
204 :
205 : // Optional call to connect the thread name with this loop.
206 11 : void set_thread_name(const std::string& aThreadName) {
207 11 : DCHECK(thread_name_.empty()) << "Should not rename this thread!";
208 11 : thread_name_ = aThreadName;
209 11 : }
210 8 : const std::string& thread_name() const { return thread_name_; }
211 :
212 : // Returns the MessageLoop object for the current thread, or null if none.
213 : static MessageLoop* current();
214 :
215 : // Enables or disables the recursive task processing. This happens in the case
216 : // of recursive message loops. Some unwanted message loop may occurs when
217 : // using common controls or printer functions. By default, recursive task
218 : // processing is disabled.
219 : //
220 : // The specific case where tasks get queued is:
221 : // - The thread is running a message loop.
222 : // - It receives a task #1 and execute it.
223 : // - The task #1 implicitly start a message loop, like a MessageBox in the
224 : // unit test. This can also be StartDoc or GetSaveFileName.
225 : // - The thread receives a task #2 before or while in this second message
226 : // loop.
227 : // - With NestableTasksAllowed set to true, the task #2 will run right away.
228 : // Otherwise, it will get executed right after task #1 completes at "thread
229 : // message loop level".
230 : void SetNestableTasksAllowed(bool allowed);
231 : void ScheduleWork();
232 : bool NestableTasksAllowed() const;
233 :
234 : // Enables or disables the restoration during an exception of the unhandled
235 : // exception filter that was active when Run() was called. This can happen
236 : // if some third party code call SetUnhandledExceptionFilter() and never
237 : // restores the previous filter.
238 0 : void set_exception_restoration(bool restore) {
239 0 : exception_restoration_ = restore;
240 0 : }
241 :
242 : #if defined(OS_WIN)
243 : void set_os_modal_loop(bool os_modal_loop) {
244 : os_modal_loop_ = os_modal_loop;
245 : }
246 :
247 : bool & os_modal_loop() {
248 : return os_modal_loop_;
249 : }
250 : #endif // OS_WIN
251 :
252 : // Set the timeouts for background hang monitoring.
253 : // A value of 0 indicates there is no timeout.
254 11 : void set_hang_timeouts(uint32_t transient_timeout_ms,
255 : uint32_t permanent_timeout_ms) {
256 11 : transient_hang_timeout_ = transient_timeout_ms;
257 11 : permanent_hang_timeout_ = permanent_timeout_ms;
258 11 : }
259 8 : uint32_t transient_hang_timeout() const {
260 8 : return transient_hang_timeout_;
261 : }
262 8 : uint32_t permanent_hang_timeout() const {
263 8 : return permanent_hang_timeout_;
264 : }
265 :
266 : //----------------------------------------------------------------------------
267 : protected:
268 69 : struct RunState {
269 : // Used to count how many Run() invocations are on the stack.
270 : int run_depth;
271 :
272 : // Used to record that Quit() was called, or that we should quit the pump
273 : // once it becomes idle.
274 : bool quit_received;
275 :
276 : #if defined(OS_WIN)
277 : base::MessagePumpWin::Dispatcher* dispatcher;
278 : #endif
279 : };
280 :
281 : class AutoRunState : RunState {
282 : public:
283 : explicit AutoRunState(MessageLoop* loop);
284 : ~AutoRunState();
285 : private:
286 : MessageLoop* loop_;
287 : RunState* previous_state_;
288 : };
289 :
290 : // This structure is copied around by value.
291 6338 : struct PendingTask {
292 : nsCOMPtr<nsIRunnable> task; // The task to run.
293 : base::TimeTicks delayed_run_time; // The time when the task should be run.
294 : int sequence_num; // Secondary sort key for run time.
295 : bool nestable; // OK to dispatch from a nested loop.
296 :
297 1238 : PendingTask(already_AddRefed<nsIRunnable> aTask, bool aNestable)
298 1238 : : task(aTask), sequence_num(0), nestable(aNestable) {
299 1238 : }
300 :
301 4051 : PendingTask(PendingTask&& aOther)
302 8103 : : task(aOther.task.forget()),
303 : delayed_run_time(aOther.delayed_run_time),
304 4052 : sequence_num(aOther.sequence_num),
305 12154 : nestable(aOther.nestable) {
306 4052 : }
307 :
308 : // std::priority_queue<T>::top is dumb, so we have to have this.
309 1047 : PendingTask(const PendingTask& aOther)
310 1047 : : task(aOther.task),
311 : delayed_run_time(aOther.delayed_run_time),
312 1047 : sequence_num(aOther.sequence_num),
313 2094 : nestable(aOther.nestable) {
314 1047 : }
315 525 : PendingTask& operator=(const PendingTask& aOther)
316 : {
317 525 : task = aOther.task;
318 525 : delayed_run_time = aOther.delayed_run_time;
319 525 : sequence_num = aOther.sequence_num;
320 525 : nestable = aOther.nestable;
321 525 : return *this;
322 : }
323 :
324 : // Used to support sorting.
325 : bool operator<(const PendingTask& other) const;
326 : };
327 :
328 : typedef std::queue<PendingTask> TaskQueue;
329 : typedef std::priority_queue<PendingTask> DelayedTaskQueue;
330 :
331 : #if defined(OS_WIN)
332 : base::MessagePumpWin* pump_win() {
333 : return static_cast<base::MessagePumpWin*>(pump_.get());
334 : }
335 : #elif defined(OS_POSIX)
336 37 : base::MessagePumpLibevent* pump_libevent() {
337 37 : return static_cast<base::MessagePumpLibevent*>(pump_.get());
338 : }
339 : #endif
340 :
341 : // A function to encapsulate all the exception handling capability in the
342 : // stacks around the running of a main message loop. It will run the message
343 : // loop in a SEH try block or not depending on the set_SEH_restoration()
344 : // flag.
345 : void RunHandler();
346 :
347 : // A surrounding stack frame around the running of the message loop that
348 : // supports all saving and restoring of state, as is needed for any/all (ugly)
349 : // recursive calls.
350 : void RunInternal();
351 :
352 : // Called to process any delayed non-nestable tasks.
353 : bool ProcessNextDelayedNonNestableTask();
354 :
355 : //----------------------------------------------------------------------------
356 : // Run a work_queue_ task or new_task, and delete it (if it was processed by
357 : // PostTask). If there are queued tasks, the oldest one is executed and
358 : // new_task is queued. new_task is optional and can be NULL. In this NULL
359 : // case, the method will run one pending task (if any exist). Returns true if
360 : // it executes a task. Queued tasks accumulate only when there is a
361 : // non-nestable task currently processing, in which case the new_task is
362 : // appended to the list work_queue_. Such re-entrancy generally happens when
363 : // an unrequested message pump (typical of a native dialog) is executing in
364 : // the context of a task.
365 : bool QueueOrRunTask(already_AddRefed<nsIRunnable> new_task);
366 :
367 : // Runs the specified task and deletes it.
368 : void RunTask(already_AddRefed<nsIRunnable> task);
369 :
370 : // Calls RunTask or queues the pending_task on the deferred task list if it
371 : // cannot be run right now. Returns true if the task was run.
372 : bool DeferOrRunPendingTask(PendingTask&& pending_task);
373 :
374 : // Adds the pending task to delayed_work_queue_.
375 : void AddToDelayedWorkQueue(const PendingTask& pending_task);
376 :
377 : // Load tasks from the incoming_queue_ into work_queue_ if the latter is
378 : // empty. The former requires a lock to access, while the latter is directly
379 : // accessible on this thread.
380 : void ReloadWorkQueue();
381 :
382 : // Delete tasks that haven't run yet without running them. Used in the
383 : // destructor to make sure all the task's destructors get called. Returns
384 : // true if some work was done.
385 : bool DeletePendingTasks();
386 :
387 : // Post a task to our incomming queue.
388 : void PostTask_Helper(already_AddRefed<nsIRunnable> task, int delay_ms);
389 :
390 : // base::MessagePump::Delegate methods:
391 : virtual bool DoWork() override;
392 : virtual bool DoDelayedWork(base::TimeTicks* next_delayed_work_time) override;
393 : virtual bool DoIdleWork() override;
394 :
395 : Type type_;
396 : int32_t id_;
397 :
398 : // A list of tasks that need to be processed by this instance. Note that
399 : // this queue is only accessed (push/pop) by our current thread.
400 : TaskQueue work_queue_;
401 :
402 : // Contains delayed tasks, sorted by their 'delayed_run_time' property.
403 : DelayedTaskQueue delayed_work_queue_;
404 :
405 : // A queue of non-nestable tasks that we had to defer because when it came
406 : // time to execute them we were in a nested message loop. They will execute
407 : // once we're out of nested message loops.
408 : TaskQueue deferred_non_nestable_work_queue_;
409 :
410 : RefPtr<base::MessagePump> pump_;
411 :
412 : base::ObserverList<DestructionObserver> destruction_observers_;
413 :
414 : // A recursion block that prevents accidentally running additonal tasks when
415 : // insider a (accidentally induced?) nested message pump.
416 : bool nestable_tasks_allowed_;
417 :
418 : bool exception_restoration_;
419 :
420 : std::string thread_name_;
421 :
422 : // A null terminated list which creates an incoming_queue of tasks that are
423 : // aquired under a mutex for processing on this instance's thread. These tasks
424 : // have not yet been sorted out into items for our work_queue_ vs items that
425 : // will be handled by the TimerManager.
426 : TaskQueue incoming_queue_;
427 : // Protect access to incoming_queue_.
428 : Lock incoming_queue_lock_;
429 :
430 : RunState* state_;
431 : int run_depth_base_;
432 :
433 : #if defined(OS_WIN)
434 : // Should be set to true before calling Windows APIs like TrackPopupMenu, etc
435 : // which enter a modal message loop.
436 : bool os_modal_loop_;
437 : #endif
438 :
439 : // Timeout values for hang monitoring
440 : uint32_t transient_hang_timeout_;
441 : uint32_t permanent_hang_timeout_;
442 :
443 : // The next sequence number to use for delayed tasks.
444 : int next_sequence_num_;
445 :
446 : class EventTarget;
447 : RefPtr<EventTarget> mEventTarget;
448 :
449 : DISALLOW_COPY_AND_ASSIGN(MessageLoop);
450 : };
451 :
452 : //-----------------------------------------------------------------------------
453 : // MessageLoopForUI extends MessageLoop with methods that are particular to a
454 : // MessageLoop instantiated with TYPE_UI.
455 : //
456 : // This class is typically used like so:
457 : // MessageLoopForUI::current()->...call some method...
458 : //
459 0 : class MessageLoopForUI : public MessageLoop {
460 : public:
461 1 : explicit MessageLoopForUI(Type aType=TYPE_UI) : MessageLoop(aType) {
462 1 : }
463 :
464 : // Returns the MessageLoopForUI of the current thread.
465 : static MessageLoopForUI* current() {
466 : MessageLoop* loop = MessageLoop::current();
467 : if (!loop)
468 : return NULL;
469 : Type type = loop->type();
470 : DCHECK(type == MessageLoop::TYPE_UI ||
471 : type == MessageLoop::TYPE_MOZILLA_PARENT ||
472 : type == MessageLoop::TYPE_MOZILLA_CHILD);
473 : return static_cast<MessageLoopForUI*>(loop);
474 : }
475 :
476 : #if defined(OS_WIN)
477 : typedef base::MessagePumpWin::Dispatcher Dispatcher;
478 : typedef base::MessagePumpWin::Observer Observer;
479 :
480 : // Please see MessagePumpWin for definitions of these methods.
481 : void Run(Dispatcher* dispatcher);
482 : void AddObserver(Observer* observer);
483 : void RemoveObserver(Observer* observer);
484 : void WillProcessMessage(const MSG& message);
485 : void DidProcessMessage(const MSG& message);
486 : void PumpOutPendingPaintMessages();
487 :
488 : protected:
489 : // TODO(rvargas): Make this platform independent.
490 : base::MessagePumpForUI* pump_ui() {
491 : return static_cast<base::MessagePumpForUI*>(pump_.get());
492 : }
493 : #endif // defined(OS_WIN)
494 : };
495 :
496 : // Do not add any member variables to MessageLoopForUI! This is important b/c
497 : // MessageLoopForUI is often allocated via MessageLoop(TYPE_UI). Any extra
498 : // data that you need should be stored on the MessageLoop's pump_ instance.
499 : COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForUI),
500 : MessageLoopForUI_should_not_have_extra_member_variables);
501 :
502 : //-----------------------------------------------------------------------------
503 : // MessageLoopForIO extends MessageLoop with methods that are particular to a
504 : // MessageLoop instantiated with TYPE_IO.
505 : //
506 : // This class is typically used like so:
507 : // MessageLoopForIO::current()->...call some method...
508 : //
509 : class MessageLoopForIO : public MessageLoop {
510 : public:
511 : MessageLoopForIO() : MessageLoop(TYPE_IO) {
512 : }
513 :
514 : // Returns the MessageLoopForIO of the current thread.
515 45 : static MessageLoopForIO* current() {
516 45 : MessageLoop* loop = MessageLoop::current();
517 45 : DCHECK_EQ(MessageLoop::TYPE_IO, loop->type());
518 45 : return static_cast<MessageLoopForIO*>(loop);
519 : }
520 :
521 : #if defined(OS_WIN)
522 : typedef base::MessagePumpForIO::IOHandler IOHandler;
523 : typedef base::MessagePumpForIO::IOContext IOContext;
524 :
525 : // Please see MessagePumpWin for definitions of these methods.
526 : void RegisterIOHandler(HANDLE file_handle, IOHandler* handler);
527 : bool WaitForIOCompletion(DWORD timeout, IOHandler* filter);
528 :
529 : protected:
530 : // TODO(rvargas): Make this platform independent.
531 : base::MessagePumpForIO* pump_io() {
532 : return static_cast<base::MessagePumpForIO*>(pump_.get());
533 : }
534 :
535 : #elif defined(OS_POSIX)
536 : typedef base::MessagePumpLibevent::Watcher Watcher;
537 : typedef base::MessagePumpLibevent::FileDescriptorWatcher
538 : FileDescriptorWatcher;
539 : typedef base::LineWatcher LineWatcher;
540 :
541 : enum Mode {
542 : WATCH_READ = base::MessagePumpLibevent::WATCH_READ,
543 : WATCH_WRITE = base::MessagePumpLibevent::WATCH_WRITE,
544 : WATCH_READ_WRITE = base::MessagePumpLibevent::WATCH_READ_WRITE
545 : };
546 :
547 : // Please see MessagePumpLibevent for definition.
548 : bool WatchFileDescriptor(int fd,
549 : bool persistent,
550 : Mode mode,
551 : FileDescriptorWatcher *controller,
552 : Watcher *delegate);
553 :
554 : typedef base::MessagePumpLibevent::SignalEvent SignalEvent;
555 : typedef base::MessagePumpLibevent::SignalWatcher SignalWatcher;
556 : bool CatchSignal(int sig,
557 : SignalEvent* sigevent,
558 : SignalWatcher* delegate);
559 :
560 : #endif // defined(OS_POSIX)
561 : };
562 :
563 : // Do not add any member variables to MessageLoopForIO! This is important b/c
564 : // MessageLoopForIO is often allocated via MessageLoop(TYPE_IO). Any extra
565 : // data that you need should be stored on the MessageLoop's pump_ instance.
566 : COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO),
567 : MessageLoopForIO_should_not_have_extra_member_variables);
568 :
569 : #endif // BASE_MESSAGE_LOOP_H_
|