blob: 0b89e28f676d9ba4a52149f3757bad16bf9681cf [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// 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.commitd7cae122008-07-26 21:49:384
[email protected]fc7fb6e2008-08-16 03:09:055#ifndef BASE_MESSAGE_LOOP_H_
6#define BASE_MESSAGE_LOOP_H_
initial.commitd7cae122008-07-26 21:49:387
initial.commitd7cae122008-07-26 21:49:388#include <deque>
9#include <queue>
10#include <string>
11#include <vector>
12
13#include "base/histogram.h"
[email protected]fc7fb6e2008-08-16 03:09:0514#include "base/message_pump.h"
initial.commitd7cae122008-07-26 21:49:3815#include "base/observer_list.h"
[email protected]fc7fb6e2008-08-16 03:09:0516#include "base/ref_counted.h"
[email protected]1fec8402009-03-13 19:11:5917#include "base/scoped_ptr.h"
initial.commitd7cae122008-07-26 21:49:3818#include "base/task.h"
19#include "base/timer.h"
initial.commitd7cae122008-07-26 21:49:3820
[email protected]fc7fb6e2008-08-16 03:09:0521#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"
[email protected]36987e92008-09-18 18:46:2625#elif defined(OS_POSIX)
26#include "base/message_pump_libevent.h"
[email protected]fc7fb6e2008-08-16 03:09:0527#endif
[email protected]faabcf42009-05-18 21:12:3428#if defined(OS_LINUX)
29#include "base/message_pump_glib.h"
30#endif
[email protected]ea15e982008-08-15 07:31:2031
[email protected]fc7fb6e2008-08-16 03:09:0532// A MessageLoop is used to process events for a particular thread. There is
33// at most one MessageLoop instance per thread.
34//
35// Events include at a minimum Task instances submitted to PostTask or those
36// managed by TimerManager. Depending on the type of message pump used by the
37// MessageLoop other events such as UI messages may be processed. On Windows
38// APC calls (as time permits) and signals sent to a registered set of HANDLEs
39// may also be processed.
initial.commitd7cae122008-07-26 21:49:3840//
41// NOTE: Unless otherwise specified, a MessageLoop's methods may only be called
42// on the thread where the MessageLoop's Run method executes.
43//
[email protected]fc7fb6e2008-08-16 03:09:0544// NOTE: MessageLoop has task reentrancy protection. This means that if a
initial.commitd7cae122008-07-26 21:49:3845// task is being processed, a second task cannot start until the first task is
[email protected]fc7fb6e2008-08-16 03:09:0546// finished. Reentrancy can happen when processing a task, and an inner
47// message pump is created. That inner pump then processes native messages
48// which could implicitly start an inner task. Inner message pumps are created
49// with dialogs (DialogBox), common dialogs (GetOpenFileName), OLE functions
50// (DoDragDrop), printer functions (StartDoc) and *many* others.
51//
initial.commitd7cae122008-07-26 21:49:3852// Sample workaround when inner task processing is needed:
53// bool old_state = MessageLoop::current()->NestableTasksAllowed();
54// MessageLoop::current()->SetNestableTasksAllowed(true);
55// HRESULT hr = DoDragDrop(...); // Implicitly runs a modal message loop here.
56// MessageLoop::current()->SetNestableTasksAllowed(old_state);
57// // Process hr (the result returned by DoDragDrop().
58//
[email protected]fc7fb6e2008-08-16 03:09:0559// Please be SURE your task is reentrant (nestable) and all global variables
60// are stable and accessible before calling SetNestableTasksAllowed(true).
initial.commitd7cae122008-07-26 21:49:3861//
[email protected]fc7fb6e2008-08-16 03:09:0562class MessageLoop : public base::MessagePump::Delegate {
initial.commitd7cae122008-07-26 21:49:3863 public:
initial.commitd7cae122008-07-26 21:49:3864 static void EnableHistogrammer(bool enable_histogrammer);
65
[email protected]ee132ad2008-08-06 21:27:0266 // A DestructionObserver is notified when the current MessageLoop is being
67 // destroyed. These obsevers are notified prior to MessageLoop::current()
68 // being changed to return NULL. This gives interested parties the chance to
69 // do final cleanup that depends on the MessageLoop.
70 //
71 // NOTE: Any tasks posted to the MessageLoop during this notification will
72 // not be run. Instead, they will be deleted.
73 //
74 class DestructionObserver {
75 public:
76 virtual ~DestructionObserver() {}
77 virtual void WillDestroyCurrentMessageLoop() = 0;
78 };
79
80 // Add a DestructionObserver, which will start receiving notifications
81 // immediately.
82 void AddDestructionObserver(DestructionObserver* destruction_observer);
83
84 // Remove a DestructionObserver. It is safe to call this method while a
85 // DestructionObserver is receiving a notification callback.
86 void RemoveDestructionObserver(DestructionObserver* destruction_observer);
87
[email protected]752578562008-09-07 08:08:2988 // The "PostTask" family of methods call the task's Run method asynchronously
89 // from within a message loop at some point in the future.
initial.commitd7cae122008-07-26 21:49:3890 //
[email protected]752578562008-09-07 08:08:2991 // With the PostTask variant, tasks are invoked in FIFO order, inter-mixed
92 // with normal UI or IO event processing. With the PostDelayedTask variant,
93 // tasks are called after at least approximately 'delay_ms' have elapsed.
initial.commitd7cae122008-07-26 21:49:3894 //
[email protected]752578562008-09-07 08:08:2995 // The NonNestable variants work similarly except that they promise never to
96 // dispatch the task from a nested invocation of MessageLoop::Run. Instead,
97 // such tasks get deferred until the top-most MessageLoop::Run is executing.
98 //
99 // The MessageLoop takes ownership of the Task, and deletes it after it has
100 // been Run().
101 //
102 // NOTE: These methods may be called on any thread. The Task will be invoked
initial.commitd7cae122008-07-26 21:49:38103 // on the thread that executes MessageLoop::Run().
[email protected]b0992172008-10-27 18:54:18104
[email protected]752578562008-09-07 08:08:29105 void PostTask(
106 const tracked_objects::Location& from_here, Task* task);
[email protected]b0992172008-10-27 18:54:18107
[email protected]752578562008-09-07 08:08:29108 void PostDelayedTask(
109 const tracked_objects::Location& from_here, Task* task, int delay_ms);
initial.commitd7cae122008-07-26 21:49:38110
[email protected]752578562008-09-07 08:08:29111 void PostNonNestableTask(
112 const tracked_objects::Location& from_here, Task* task);
initial.commitd7cae122008-07-26 21:49:38113
[email protected]752578562008-09-07 08:08:29114 void PostNonNestableDelayedTask(
115 const tracked_objects::Location& from_here, Task* task, int delay_ms);
initial.commitd7cae122008-07-26 21:49:38116
117 // A variant on PostTask that deletes the given object. This is useful
118 // if the object needs to live until the next run of the MessageLoop (for
119 // example, deleting a RenderProcessHost from within an IPC callback is not
120 // good).
121 //
122 // NOTE: This method may be called on any thread. The object will be deleted
123 // on the thread that executes MessageLoop::Run(). If this is not the same
124 // as the thread that calls PostDelayedTask(FROM_HERE, ), then T MUST inherit
125 // from RefCountedThreadSafe<T>!
126 template <class T>
127 void DeleteSoon(const tracked_objects::Location& from_here, T* object) {
[email protected]752578562008-09-07 08:08:29128 PostNonNestableTask(from_here, new DeleteTask<T>(object));
initial.commitd7cae122008-07-26 21:49:38129 }
130
131 // A variant on PostTask that releases the given reference counted object
132 // (by calling its Release method). This is useful if the object needs to
133 // live until the next run of the MessageLoop, or if the object needs to be
134 // released on a particular thread.
135 //
136 // NOTE: This method may be called on any thread. The object will be
137 // released (and thus possibly deleted) on the thread that executes
138 // MessageLoop::Run(). If this is not the same as the thread that calls
139 // PostDelayedTask(FROM_HERE, ), then T MUST inherit from
140 // RefCountedThreadSafe<T>!
141 template <class T>
142 void ReleaseSoon(const tracked_objects::Location& from_here, T* object) {
[email protected]752578562008-09-07 08:08:29143 PostNonNestableTask(from_here, new ReleaseTask<T>(object));
initial.commitd7cae122008-07-26 21:49:38144 }
145
[email protected]3882c4332008-07-30 19:03:59146 // Run the message loop.
initial.commitd7cae122008-07-26 21:49:38147 void Run();
148
[email protected]7e0e8762008-07-31 13:10:20149 // Process all pending tasks, windows messages, etc., but don't wait/sleep.
150 // Return as soon as all items that can be run are taken care of.
151 void RunAllPending();
[email protected]3882c4332008-07-30 19:03:59152
initial.commitd7cae122008-07-26 21:49:38153 // Signals the Run method to return after it is done processing all pending
[email protected]fc7fb6e2008-08-16 03:09:05154 // messages. This method may only be called on the same thread that called
155 // Run, and Run must still be on the call stack.
initial.commitd7cae122008-07-26 21:49:38156 //
[email protected]fc7fb6e2008-08-16 03:09:05157 // Use QuitTask if you need to Quit another thread's MessageLoop, but note
158 // that doing so is fairly dangerous if the target thread makes nested calls
159 // to MessageLoop::Run. The problem being that you won't know which nested
160 // run loop you are quiting, so be careful!
161 //
initial.commitd7cae122008-07-26 21:49:38162 void Quit();
163
[email protected]fc7fb6e2008-08-16 03:09:05164 // Invokes Quit on the current MessageLoop when run. Useful to schedule an
initial.commitd7cae122008-07-26 21:49:38165 // arbitrary MessageLoop to Quit.
166 class QuitTask : public Task {
167 public:
168 virtual void Run() {
169 MessageLoop::current()->Quit();
170 }
171 };
172
[email protected]4d9bdfaf2008-08-26 05:53:57173 // A MessageLoop has a particular type, which indicates the set of
174 // asynchronous events it may process in addition to tasks and timers.
175 //
176 // TYPE_DEFAULT
177 // This type of ML only supports tasks and timers.
178 //
179 // TYPE_UI
180 // This type of ML also supports native UI events (e.g., Windows messages).
181 // See also MessageLoopForUI.
182 //
183 // TYPE_IO
184 // This type of ML also supports asynchronous IO. See also
185 // MessageLoopForIO.
186 //
187 enum Type {
188 TYPE_DEFAULT,
189 TYPE_UI,
190 TYPE_IO
191 };
192
initial.commitd7cae122008-07-26 21:49:38193 // Normally, it is not necessary to instantiate a MessageLoop. Instead, it
194 // is typical to make use of the current thread's MessageLoop instance.
[email protected]4d9bdfaf2008-08-26 05:53:57195 explicit MessageLoop(Type type = TYPE_DEFAULT);
initial.commitd7cae122008-07-26 21:49:38196 ~MessageLoop();
197
[email protected]4d9bdfaf2008-08-26 05:53:57198 // Returns the type passed to the constructor.
199 Type type() const { return type_; }
200
initial.commitd7cae122008-07-26 21:49:38201 // Optional call to connect the thread name with this loop.
[email protected]fc7fb6e2008-08-16 03:09:05202 void set_thread_name(const std::string& thread_name) {
203 DCHECK(thread_name_.empty()) << "Should not rename this thread!";
204 thread_name_ = thread_name;
205 }
[email protected]ee132ad2008-08-06 21:27:02206 const std::string& thread_name() const { return thread_name_; }
initial.commitd7cae122008-07-26 21:49:38207
208 // Returns the MessageLoop object for the current thread, or null if none.
[email protected]f886b7bf2008-09-10 10:54:06209 static MessageLoop* current();
initial.commitd7cae122008-07-26 21:49:38210
initial.commitd7cae122008-07-26 21:49:38211 // Enables or disables the recursive task processing. This happens in the case
212 // of recursive message loops. Some unwanted message loop may occurs when
213 // using common controls or printer functions. By default, recursive task
214 // processing is disabled.
215 //
216 // The specific case where tasks get queued is:
217 // - The thread is running a message loop.
218 // - It receives a task #1 and execute it.
219 // - The task #1 implicitly start a message loop, like a MessageBox in the
220 // unit test. This can also be StartDoc or GetSaveFileName.
221 // - The thread receives a task #2 before or while in this second message
222 // loop.
223 // - With NestableTasksAllowed set to true, the task #2 will run right away.
224 // Otherwise, it will get executed right after task #1 completes at "thread
225 // message loop level".
226 void SetNestableTasksAllowed(bool allowed);
227 bool NestableTasksAllowed() const;
228
229 // Enables or disables the restoration during an exception of the unhandled
230 // exception filter that was active when Run() was called. This can happen
231 // if some third party code call SetUnhandledExceptionFilter() and never
232 // restores the previous filter.
233 void set_exception_restoration(bool restore) {
234 exception_restoration_ = restore;
235 }
236
initial.commitd7cae122008-07-26 21:49:38237 //----------------------------------------------------------------------------
[email protected]4d9bdfaf2008-08-26 05:53:57238 protected:
[email protected]fc7fb6e2008-08-16 03:09:05239 struct RunState {
240 // Used to count how many Run() invocations are on the stack.
241 int run_depth;
initial.commitd7cae122008-07-26 21:49:38242
[email protected]fc7fb6e2008-08-16 03:09:05243 // Used to record that Quit() was called, or that we should quit the pump
244 // once it becomes idle.
245 bool quit_received;
initial.commitd7cae122008-07-26 21:49:38246
[email protected]fc7fb6e2008-08-16 03:09:05247#if defined(OS_WIN)
248 base::MessagePumpWin::Dispatcher* dispatcher;
249#endif
250 };
251
252 class AutoRunState : RunState {
253 public:
[email protected]b0992172008-10-27 18:54:18254 explicit AutoRunState(MessageLoop* loop);
[email protected]fc7fb6e2008-08-16 03:09:05255 ~AutoRunState();
initial.commitd7cae122008-07-26 21:49:38256 private:
257 MessageLoop* loop_;
[email protected]fc7fb6e2008-08-16 03:09:05258 RunState* previous_state_;
259 };
initial.commitd7cae122008-07-26 21:49:38260
[email protected]752578562008-09-07 08:08:29261 // This structure is copied around by value.
262 struct PendingTask {
[email protected]e1acf6f2008-10-27 20:43:33263 Task* task; // The task to run.
264 base::Time delayed_run_time; // The time when the task should be run.
265 int sequence_num; // Used to facilitate sorting by run time.
266 bool nestable; // True if OK to dispatch from a nested loop.
initial.commitd7cae122008-07-26 21:49:38267
[email protected]752578562008-09-07 08:08:29268 PendingTask(Task* task, bool nestable)
269 : task(task), sequence_num(0), nestable(nestable) {
270 }
[email protected]b0992172008-10-27 18:54:18271
[email protected]752578562008-09-07 08:08:29272 // Used to support sorting.
273 bool operator<(const PendingTask& other) const;
initial.commitd7cae122008-07-26 21:49:38274 };
275
[email protected]752578562008-09-07 08:08:29276 typedef std::queue<PendingTask> TaskQueue;
[email protected]4bed5d82008-12-17 03:50:05277 typedef std::priority_queue<PendingTask> DelayedTaskQueue;
initial.commitd7cae122008-07-26 21:49:38278
[email protected]fc7fb6e2008-08-16 03:09:05279#if defined(OS_WIN)
280 base::MessagePumpWin* pump_win() {
281 return static_cast<base::MessagePumpWin*>(pump_.get());
282 }
[email protected]36987e92008-09-18 18:46:26283#elif defined(OS_POSIX)
284 base::MessagePumpLibevent* pump_libevent() {
285 return static_cast<base::MessagePumpLibevent*>(pump_.get());
286 }
[email protected]fc7fb6e2008-08-16 03:09:05287#endif
[email protected]3882c4332008-07-30 19:03:59288
289 // A function to encapsulate all the exception handling capability in the
[email protected]fc7fb6e2008-08-16 03:09:05290 // stacks around the running of a main message loop. It will run the message
291 // loop in a SEH try block or not depending on the set_SEH_restoration()
292 // flag.
293 void RunHandler();
initial.commitd7cae122008-07-26 21:49:38294
[email protected]3882c4332008-07-30 19:03:59295 // A surrounding stack frame around the running of the message loop that
296 // supports all saving and restoring of state, as is needed for any/all (ugly)
297 // recursive calls.
[email protected]fc7fb6e2008-08-16 03:09:05298 void RunInternal();
[email protected]ea15e982008-08-15 07:31:20299
[email protected]fc7fb6e2008-08-16 03:09:05300 // Called to process any delayed non-nestable tasks.
initial.commitd7cae122008-07-26 21:49:38301 bool ProcessNextDelayedNonNestableTask();
initial.commitd7cae122008-07-26 21:49:38302
303 //----------------------------------------------------------------------------
initial.commitd7cae122008-07-26 21:49:38304 // Run a work_queue_ task or new_task, and delete it (if it was processed by
305 // PostTask). If there are queued tasks, the oldest one is executed and
306 // new_task is queued. new_task is optional and can be NULL. In this NULL
307 // case, the method will run one pending task (if any exist). Returns true if
[email protected]fc7fb6e2008-08-16 03:09:05308 // it executes a task. Queued tasks accumulate only when there is a
309 // non-nestable task currently processing, in which case the new_task is
310 // appended to the list work_queue_. Such re-entrancy generally happens when
311 // an unrequested message pump (typical of a native dialog) is executing in
312 // the context of a task.
initial.commitd7cae122008-07-26 21:49:38313 bool QueueOrRunTask(Task* new_task);
314
315 // Runs the specified task and deletes it.
316 void RunTask(Task* task);
317
[email protected]752578562008-09-07 08:08:29318 // Calls RunTask or queues the pending_task on the deferred task list if it
319 // cannot be run right now. Returns true if the task was run.
320 bool DeferOrRunPendingTask(const PendingTask& pending_task);
initial.commitd7cae122008-07-26 21:49:38321
[email protected]001747c2008-09-10 00:37:07322 // Adds the pending task to delayed_work_queue_.
323 void AddToDelayedWorkQueue(const PendingTask& pending_task);
324
initial.commitd7cae122008-07-26 21:49:38325 // Load tasks from the incoming_queue_ into work_queue_ if the latter is
326 // empty. The former requires a lock to access, while the latter is directly
327 // accessible on this thread.
328 void ReloadWorkQueue();
329
330 // Delete tasks that haven't run yet without running them. Used in the
[email protected]001747c2008-09-10 00:37:07331 // destructor to make sure all the task's destructors get called. Returns
332 // true if some work was done.
333 bool DeletePendingTasks();
initial.commitd7cae122008-07-26 21:49:38334
initial.commitd7cae122008-07-26 21:49:38335 // Post a task to our incomming queue.
[email protected]752578562008-09-07 08:08:29336 void PostTask_Helper(const tracked_objects::Location& from_here, Task* task,
337 int delay_ms, bool nestable);
[email protected]fc7fb6e2008-08-16 03:09:05338
339 // base::MessagePump::Delegate methods:
340 virtual bool DoWork();
[email protected]e1acf6f2008-10-27 20:43:33341 virtual bool DoDelayedWork(base::Time* next_delayed_work_time);
[email protected]fc7fb6e2008-08-16 03:09:05342 virtual bool DoIdleWork();
343
initial.commitd7cae122008-07-26 21:49:38344 // Start recording histogram info about events and action IF it was enabled
345 // and IF the statistics recorder can accept a registration of our histogram.
346 void StartHistogrammer();
347
348 // Add occurence of event to our histogram, so that we can see what is being
349 // done in a specific MessageLoop instance (i.e., specific thread).
350 // If message_histogram_ is NULL, this is a no-op.
351 void HistogramEvent(int event);
352
initial.commitd7cae122008-07-26 21:49:38353 static const LinearHistogram::DescriptionPair event_descriptions_[];
354 static bool enable_histogrammer_;
355
[email protected]4d9bdfaf2008-08-26 05:53:57356 Type type_;
357
[email protected]752578562008-09-07 08:08:29358 // A list of tasks that need to be processed by this instance. Note that
359 // this queue is only accessed (push/pop) by our current thread.
360 TaskQueue work_queue_;
[email protected]b0992172008-10-27 18:54:18361
[email protected]752578562008-09-07 08:08:29362 // Contains delayed tasks, sorted by their 'delayed_run_time' property.
363 DelayedTaskQueue delayed_work_queue_;
initial.commitd7cae122008-07-26 21:49:38364
[email protected]752578562008-09-07 08:08:29365 // A queue of non-nestable tasks that we had to defer because when it came
366 // time to execute them we were in a nested message loop. They will execute
367 // once we're out of nested message loops.
368 TaskQueue deferred_non_nestable_work_queue_;
initial.commitd7cae122008-07-26 21:49:38369
[email protected]fc7fb6e2008-08-16 03:09:05370 scoped_refptr<base::MessagePump> pump_;
[email protected]ee132ad2008-08-06 21:27:02371
[email protected]2a127252008-08-05 23:16:41372 ObserverList<DestructionObserver> destruction_observers_;
[email protected]001747c2008-09-10 00:37:07373
initial.commitd7cae122008-07-26 21:49:38374 // A recursion block that prevents accidentally running additonal tasks when
375 // insider a (accidentally induced?) nested message pump.
376 bool nestable_tasks_allowed_;
377
378 bool exception_restoration_;
379
initial.commitd7cae122008-07-26 21:49:38380 std::string thread_name_;
381 // A profiling histogram showing the counts of various messages and events.
382 scoped_ptr<LinearHistogram> message_histogram_;
383
384 // A null terminated list which creates an incoming_queue of tasks that are
385 // aquired under a mutex for processing on this instance's thread. These tasks
386 // have not yet been sorted out into items for our work_queue_ vs items that
387 // will be handled by the TimerManager.
388 TaskQueue incoming_queue_;
389 // Protect access to incoming_queue_.
390 Lock incoming_queue_lock_;
391
[email protected]fc7fb6e2008-08-16 03:09:05392 RunState* state_;
initial.commitd7cae122008-07-26 21:49:38393
[email protected]752578562008-09-07 08:08:29394 // The next sequence number to use for delayed tasks.
395 int next_sequence_num_;
396
[email protected]fc7fb6e2008-08-16 03:09:05397 DISALLOW_COPY_AND_ASSIGN(MessageLoop);
initial.commitd7cae122008-07-26 21:49:38398};
399
[email protected]4d9bdfaf2008-08-26 05:53:57400//-----------------------------------------------------------------------------
401// MessageLoopForUI extends MessageLoop with methods that are particular to a
402// MessageLoop instantiated with TYPE_UI.
403//
404// This class is typically used like so:
405// MessageLoopForUI::current()->...call some method...
406//
407class MessageLoopForUI : public MessageLoop {
408 public:
409 MessageLoopForUI() : MessageLoop(TYPE_UI) {
410 }
license.botbf09a502008-08-24 00:55:55411
[email protected]4d9bdfaf2008-08-26 05:53:57412 // Returns the MessageLoopForUI of the current thread.
413 static MessageLoopForUI* current() {
414 MessageLoop* loop = MessageLoop::current();
415 DCHECK_EQ(MessageLoop::TYPE_UI, loop->type());
416 return static_cast<MessageLoopForUI*>(loop);
417 }
418
[email protected]faabcf42009-05-18 21:12:34419#if defined(OS_LINUX)
420 typedef base::MessagePumpForUI::Observer Observer;
421
422 // See message_pump_glib for definitions of these methods.
423 void AddObserver(Observer* observer);
424 void RemoveObserver(Observer* observer);
425#endif
426
[email protected]4d9bdfaf2008-08-26 05:53:57427#if defined(OS_WIN)
428 typedef base::MessagePumpWin::Dispatcher Dispatcher;
429 typedef base::MessagePumpWin::Observer Observer;
430
431 // Please see MessagePumpWin for definitions of these methods.
[email protected]4d9bdfaf2008-08-26 05:53:57432 void AddObserver(Observer* observer);
433 void RemoveObserver(Observer* observer);
[email protected]faabcf42009-05-18 21:12:34434 void Run(Dispatcher* dispatcher);
[email protected]4d9bdfaf2008-08-26 05:53:57435 void WillProcessMessage(const MSG& message);
436 void DidProcessMessage(const MSG& message);
437 void PumpOutPendingPaintMessages();
[email protected]faabcf42009-05-18 21:12:34438#endif
[email protected]1a8f5d1d2008-09-25 20:33:04439
[email protected]faabcf42009-05-18 21:12:34440#if defined(OS_WIN) || defined(OS_LINUX)
[email protected]1a8f5d1d2008-09-25 20:33:04441 protected:
442 // TODO(rvargas): Make this platform independent.
[email protected]17b89142008-11-07 21:52:15443 base::MessagePumpForUI* pump_ui() {
[email protected]1a8f5d1d2008-09-25 20:33:04444 return static_cast<base::MessagePumpForUI*>(pump_.get());
445 }
[email protected]4d9bdfaf2008-08-26 05:53:57446#endif // defined(OS_WIN)
447};
448
449// Do not add any member variables to MessageLoopForUI! This is important b/c
450// MessageLoopForUI is often allocated via MessageLoop(TYPE_UI). Any extra
451// data that you need should be stored on the MessageLoop's pump_ instance.
452COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForUI),
453 MessageLoopForUI_should_not_have_extra_member_variables);
454
455//-----------------------------------------------------------------------------
456// MessageLoopForIO extends MessageLoop with methods that are particular to a
457// MessageLoop instantiated with TYPE_IO.
458//
459// This class is typically used like so:
460// MessageLoopForIO::current()->...call some method...
461//
462class MessageLoopForIO : public MessageLoop {
463 public:
464 MessageLoopForIO() : MessageLoop(TYPE_IO) {
465 }
466
467 // Returns the MessageLoopForIO of the current thread.
468 static MessageLoopForIO* current() {
469 MessageLoop* loop = MessageLoop::current();
470 DCHECK_EQ(MessageLoop::TYPE_IO, loop->type());
471 return static_cast<MessageLoopForIO*>(loop);
472 }
473
474#if defined(OS_WIN)
[email protected]32cda29d2008-10-09 23:58:43475 typedef base::MessagePumpForIO::IOHandler IOHandler;
[email protected]17b89142008-11-07 21:52:15476 typedef base::MessagePumpForIO::IOContext IOContext;
[email protected]4d9bdfaf2008-08-26 05:53:57477
478 // Please see MessagePumpWin for definitions of these methods.
[email protected]32cda29d2008-10-09 23:58:43479 void RegisterIOHandler(HANDLE file_handle, IOHandler* handler);
[email protected]17b89142008-11-07 21:52:15480 bool WaitForIOCompletion(DWORD timeout, IOHandler* filter);
[email protected]36987e92008-09-18 18:46:26481
[email protected]1a8f5d1d2008-09-25 20:33:04482 protected:
483 // TODO(rvargas): Make this platform independent.
484 base::MessagePumpForIO* pump_io() {
485 return static_cast<base::MessagePumpForIO*>(pump_.get());
486 }
487
[email protected]36987e92008-09-18 18:46:26488#elif defined(OS_POSIX)
489 typedef base::MessagePumpLibevent::Watcher Watcher;
[email protected]e45e6c02008-12-15 22:02:17490 typedef base::MessagePumpLibevent::FileDescriptorWatcher
491 FileDescriptorWatcher;
[email protected]36987e92008-09-18 18:46:26492
[email protected]e45e6c02008-12-15 22:02:17493 enum Mode {
494 WATCH_READ = base::MessagePumpLibevent::WATCH_READ,
495 WATCH_WRITE = base::MessagePumpLibevent::WATCH_WRITE,
496 WATCH_READ_WRITE = base::MessagePumpLibevent::WATCH_READ_WRITE
497 };
498
499 // Please see MessagePumpLibevent for definition.
500 bool WatchFileDescriptor(int fd,
501 bool persistent,
502 Mode mode,
503 FileDescriptorWatcher *controller,
504 Watcher *delegate);
[email protected]1a8f5d1d2008-09-25 20:33:04505#endif // defined(OS_POSIX)
[email protected]4d9bdfaf2008-08-26 05:53:57506};
507
508// Do not add any member variables to MessageLoopForIO! This is important b/c
509// MessageLoopForIO is often allocated via MessageLoop(TYPE_IO). Any extra
510// data that you need should be stored on the MessageLoop's pump_ instance.
511COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO),
512 MessageLoopForIO_should_not_have_extra_member_variables);
513
514#endif // BASE_MESSAGE_LOOP_H_