Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / base / message_loop / message_loop.h
1 // Copyright 2013 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.
4
5 #ifndef BASE_MESSAGE_LOOP_MESSAGE_LOOP_H_
6 #define BASE_MESSAGE_LOOP_MESSAGE_LOOP_H_
7
8 #include <queue>
9 #include <string>
10
11 #include "base/base_export.h"
12 #include "base/basictypes.h"
13 #include "base/callback_forward.h"
14 #include "base/location.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/message_loop/incoming_task_queue.h"
18 #include "base/message_loop/message_loop_proxy.h"
19 #include "base/message_loop/message_loop_proxy_impl.h"
20 #include "base/message_loop/message_pump.h"
21 #include "base/observer_list.h"
22 #include "base/pending_task.h"
23 #include "base/sequenced_task_runner_helpers.h"
24 #include "base/synchronization/lock.h"
25 #include "base/time/time.h"
26 #include "base/tracking_info.h"
27
28 // TODO(sky): these includes should not be necessary. Nuke them.
29 #if defined(OS_WIN)
30 #include "base/message_loop/message_pump_win.h"
31 #elif defined(OS_IOS)
32 #include "base/message_loop/message_pump_io_ios.h"
33 #elif defined(OS_POSIX)
34 #include "base/message_loop/message_pump_libevent.h"
35 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
36
37 #if defined(USE_AURA) && defined(USE_X11) && !defined(OS_NACL)
38 #include "base/message_loop/message_pump_x11.h"
39 #elif defined(USE_OZONE) && !defined(OS_NACL)
40 #include "base/message_loop/message_pump_ozone.h"
41 #else
42 #define USE_GTK_MESSAGE_PUMP
43 #include "base/message_loop/message_pump_gtk.h"
44 #if defined(TOOLKIT_GTK)
45 #include "base/message_loop/message_pump_x11.h"
46 #endif
47 #endif
48
49 #endif
50 #endif
51
52 namespace base {
53
54 class HistogramBase;
55 class MessagePumpObserver;
56 class RunLoop;
57 class ThreadTaskRunnerHandle;
58 #if defined(OS_ANDROID)
59 class MessagePumpForUI;
60 #endif
61 class WaitableEvent;
62
63 // A MessageLoop is used to process events for a particular thread.  There is
64 // at most one MessageLoop instance per thread.
65 //
66 // Events include at a minimum Task instances submitted to PostTask and its
67 // variants.  Depending on the type of message pump used by the MessageLoop
68 // other events such as UI messages may be processed.  On Windows APC calls (as
69 // time permits) and signals sent to a registered set of HANDLEs may also be
70 // processed.
71 //
72 // NOTE: Unless otherwise specified, a MessageLoop's methods may only be called
73 // on the thread where the MessageLoop's Run method executes.
74 //
75 // NOTE: MessageLoop has task reentrancy protection.  This means that if a
76 // task is being processed, a second task cannot start until the first task is
77 // finished.  Reentrancy can happen when processing a task, and an inner
78 // message pump is created.  That inner pump then processes native messages
79 // which could implicitly start an inner task.  Inner message pumps are created
80 // with dialogs (DialogBox), common dialogs (GetOpenFileName), OLE functions
81 // (DoDragDrop), printer functions (StartDoc) and *many* others.
82 //
83 // Sample workaround when inner task processing is needed:
84 //   HRESULT hr;
85 //   {
86 //     MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
87 //     hr = DoDragDrop(...); // Implicitly runs a modal message loop.
88 //   }
89 //   // Process |hr| (the result returned by DoDragDrop()).
90 //
91 // Please be SURE your task is reentrant (nestable) and all global variables
92 // are stable and accessible before calling SetNestableTasksAllowed(true).
93 //
94 class BASE_EXPORT MessageLoop : public MessagePump::Delegate {
95  public:
96
97 #if defined(USE_AURA)
98   typedef MessagePumpObserver Observer;
99 #elif defined(USE_GTK_MESSAGE_PUMP)
100   typedef MessagePumpGdkObserver Observer;
101 #endif
102
103   // A MessageLoop has a particular type, which indicates the set of
104   // asynchronous events it may process in addition to tasks and timers.
105   //
106   // TYPE_DEFAULT
107   //   This type of ML only supports tasks and timers.
108   //
109   // TYPE_UI
110   //   This type of ML also supports native UI events (e.g., Windows messages).
111   //   See also MessageLoopForUI.
112   //
113   // TYPE_GPU
114   //   This type of ML also supports native UI events for use in the GPU
115   //   process. On Linux this will always be an X11 ML (as compared with the
116   //   sometimes-GTK ML in the browser process).
117   //
118   // TYPE_IO
119   //   This type of ML also supports asynchronous IO.  See also
120   //   MessageLoopForIO.
121   //
122   // TYPE_JAVA
123   //   This type of ML is backed by a Java message handler which is responsible
124   //   for running the tasks added to the ML. This is only for use on Android.
125   //   TYPE_JAVA behaves in essence like TYPE_UI, except during construction
126   //   where it does not use the main thread specific pump factory.
127   //
128   // TYPE_CUSTOM
129   //   MessagePump was supplied to constructor.
130   //
131   enum Type {
132     TYPE_DEFAULT,
133     TYPE_UI,
134     TYPE_CUSTOM,
135 #if defined(TOOLKIT_GTK)
136     TYPE_GPU,
137 #endif
138     TYPE_IO,
139 #if defined(OS_ANDROID)
140     TYPE_JAVA,
141 #endif // defined(OS_ANDROID)
142   };
143
144   // Normally, it is not necessary to instantiate a MessageLoop.  Instead, it
145   // is typical to make use of the current thread's MessageLoop instance.
146   explicit MessageLoop(Type type = TYPE_DEFAULT);
147   // Creates a TYPE_CUSTOM MessageLoop with the supplied MessagePump, which must
148   // be non-NULL.
149   explicit MessageLoop(scoped_ptr<base::MessagePump> pump);
150   virtual ~MessageLoop();
151
152   // Returns the MessageLoop object for the current thread, or null if none.
153   static MessageLoop* current();
154
155   static void EnableHistogrammer(bool enable_histogrammer);
156
157   typedef MessagePump* (MessagePumpFactory)();
158   // Uses the given base::MessagePumpForUIFactory to override the default
159   // MessagePump implementation for 'TYPE_UI'. Returns true if the factory
160   // was successfully registered.
161   static bool InitMessagePumpForUIFactory(MessagePumpFactory* factory);
162
163   // Creates the default MessagePump based on |type|. Caller owns return
164   // value.
165   // TODO(sky): convert this and InitMessagePumpForUIFactory() to return a
166   // scoped_ptr.
167   static MessagePump* CreateMessagePumpForType(Type type);
168
169   // A DestructionObserver is notified when the current MessageLoop is being
170   // destroyed.  These observers are notified prior to MessageLoop::current()
171   // being changed to return NULL.  This gives interested parties the chance to
172   // do final cleanup that depends on the MessageLoop.
173   //
174   // NOTE: Any tasks posted to the MessageLoop during this notification will
175   // not be run.  Instead, they will be deleted.
176   //
177   class BASE_EXPORT DestructionObserver {
178    public:
179     virtual void WillDestroyCurrentMessageLoop() = 0;
180
181    protected:
182     virtual ~DestructionObserver();
183   };
184
185   // Add a DestructionObserver, which will start receiving notifications
186   // immediately.
187   void AddDestructionObserver(DestructionObserver* destruction_observer);
188
189   // Remove a DestructionObserver.  It is safe to call this method while a
190   // DestructionObserver is receiving a notification callback.
191   void RemoveDestructionObserver(DestructionObserver* destruction_observer);
192
193   // The "PostTask" family of methods call the task's Run method asynchronously
194   // from within a message loop at some point in the future.
195   //
196   // With the PostTask variant, tasks are invoked in FIFO order, inter-mixed
197   // with normal UI or IO event processing.  With the PostDelayedTask variant,
198   // tasks are called after at least approximately 'delay_ms' have elapsed.
199   //
200   // The NonNestable variants work similarly except that they promise never to
201   // dispatch the task from a nested invocation of MessageLoop::Run.  Instead,
202   // such tasks get deferred until the top-most MessageLoop::Run is executing.
203   //
204   // The MessageLoop takes ownership of the Task, and deletes it after it has
205   // been Run().
206   //
207   // PostTask(from_here, task) is equivalent to
208   // PostDelayedTask(from_here, task, 0).
209   //
210   // NOTE: These methods may be called on any thread.  The Task will be invoked
211   // on the thread that executes MessageLoop::Run().
212   void PostTask(const tracked_objects::Location& from_here,
213                 const Closure& task);
214
215   void PostDelayedTask(const tracked_objects::Location& from_here,
216                        const Closure& task,
217                        TimeDelta delay);
218
219   void PostNonNestableTask(const tracked_objects::Location& from_here,
220                            const Closure& task);
221
222   void PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
223                                   const Closure& task,
224                                   TimeDelta delay);
225
226   // A variant on PostTask that deletes the given object.  This is useful
227   // if the object needs to live until the next run of the MessageLoop (for
228   // example, deleting a RenderProcessHost from within an IPC callback is not
229   // good).
230   //
231   // NOTE: This method may be called on any thread.  The object will be deleted
232   // on the thread that executes MessageLoop::Run().  If this is not the same
233   // as the thread that calls PostDelayedTask(FROM_HERE, ), then T MUST inherit
234   // from RefCountedThreadSafe<T>!
235   template <class T>
236   void DeleteSoon(const tracked_objects::Location& from_here, const T* object) {
237     base::subtle::DeleteHelperInternal<T, void>::DeleteViaSequencedTaskRunner(
238         this, from_here, object);
239   }
240
241   // A variant on PostTask that releases the given reference counted object
242   // (by calling its Release method).  This is useful if the object needs to
243   // live until the next run of the MessageLoop, or if the object needs to be
244   // released on a particular thread.
245   //
246   // NOTE: This method may be called on any thread.  The object will be
247   // released (and thus possibly deleted) on the thread that executes
248   // MessageLoop::Run().  If this is not the same as the thread that calls
249   // PostDelayedTask(FROM_HERE, ), then T MUST inherit from
250   // RefCountedThreadSafe<T>!
251   template <class T>
252   void ReleaseSoon(const tracked_objects::Location& from_here,
253                    const T* object) {
254     base::subtle::ReleaseHelperInternal<T, void>::ReleaseViaSequencedTaskRunner(
255         this, from_here, object);
256   }
257
258   // Deprecated: use RunLoop instead.
259   // Run the message loop.
260   void Run();
261
262   // Deprecated: use RunLoop instead.
263   // Process all pending tasks, windows messages, etc., but don't wait/sleep.
264   // Return as soon as all items that can be run are taken care of.
265   void RunUntilIdle();
266
267   // TODO(jbates) remove this. crbug.com/131220. See QuitWhenIdle().
268   void Quit() { QuitWhenIdle(); }
269
270   // Deprecated: use RunLoop instead.
271   //
272   // Signals the Run method to return when it becomes idle. It will continue to
273   // process pending messages and future messages as long as they are enqueued.
274   // Warning: if the MessageLoop remains busy, it may never quit. Only use this
275   // Quit method when looping procedures (such as web pages) have been shut
276   // down.
277   //
278   // This method may only be called on the same thread that called Run, and Run
279   // must still be on the call stack.
280   //
281   // Use QuitClosure variants if you need to Quit another thread's MessageLoop,
282   // but note that doing so is fairly dangerous if the target thread makes
283   // nested calls to MessageLoop::Run.  The problem being that you won't know
284   // which nested run loop you are quitting, so be careful!
285   void QuitWhenIdle();
286
287   // Deprecated: use RunLoop instead.
288   //
289   // This method is a variant of Quit, that does not wait for pending messages
290   // to be processed before returning from Run.
291   void QuitNow();
292
293   // TODO(jbates) remove this. crbug.com/131220. See QuitWhenIdleClosure().
294   static Closure QuitClosure() { return QuitWhenIdleClosure(); }
295
296   // Deprecated: use RunLoop instead.
297   // Construct a Closure that will call QuitWhenIdle(). Useful to schedule an
298   // arbitrary MessageLoop to QuitWhenIdle.
299   static Closure QuitWhenIdleClosure();
300
301   // Returns true if this loop is |type|. This allows subclasses (especially
302   // those in tests) to specialize how they are identified.
303   virtual bool IsType(Type type) const;
304
305   // Returns the type passed to the constructor.
306   Type type() const { return type_; }
307
308   // Optional call to connect the thread name with this loop.
309   void set_thread_name(const std::string& thread_name) {
310     DCHECK(thread_name_.empty()) << "Should not rename this thread!";
311     thread_name_ = thread_name;
312   }
313   const std::string& thread_name() const { return thread_name_; }
314
315   // Gets the message loop proxy associated with this message loop.
316   scoped_refptr<MessageLoopProxy> message_loop_proxy() {
317     return message_loop_proxy_;
318   }
319
320   // Enables or disables the recursive task processing. This happens in the case
321   // of recursive message loops. Some unwanted message loop may occurs when
322   // using common controls or printer functions. By default, recursive task
323   // processing is disabled.
324   //
325   // Please utilize |ScopedNestableTaskAllower| instead of calling these methods
326   // directly.  In general nestable message loops are to be avoided.  They are
327   // dangerous and difficult to get right, so please use with extreme caution.
328   //
329   // The specific case where tasks get queued is:
330   // - The thread is running a message loop.
331   // - It receives a task #1 and execute it.
332   // - The task #1 implicitly start a message loop, like a MessageBox in the
333   //   unit test. This can also be StartDoc or GetSaveFileName.
334   // - The thread receives a task #2 before or while in this second message
335   //   loop.
336   // - With NestableTasksAllowed set to true, the task #2 will run right away.
337   //   Otherwise, it will get executed right after task #1 completes at "thread
338   //   message loop level".
339   void SetNestableTasksAllowed(bool allowed);
340   bool NestableTasksAllowed() const;
341
342   // Enables nestable tasks on |loop| while in scope.
343   class ScopedNestableTaskAllower {
344    public:
345     explicit ScopedNestableTaskAllower(MessageLoop* loop)
346         : loop_(loop),
347           old_state_(loop_->NestableTasksAllowed()) {
348       loop_->SetNestableTasksAllowed(true);
349     }
350     ~ScopedNestableTaskAllower() {
351       loop_->SetNestableTasksAllowed(old_state_);
352     }
353
354    private:
355     MessageLoop* loop_;
356     bool old_state_;
357   };
358
359   // Returns true if we are currently running a nested message loop.
360   bool IsNested();
361
362   // A TaskObserver is an object that receives task notifications from the
363   // MessageLoop.
364   //
365   // NOTE: A TaskObserver implementation should be extremely fast!
366   class BASE_EXPORT TaskObserver {
367    public:
368     TaskObserver();
369
370     // This method is called before processing a task.
371     virtual void WillProcessTask(const PendingTask& pending_task) = 0;
372
373     // This method is called after processing a task.
374     virtual void DidProcessTask(const PendingTask& pending_task) = 0;
375
376    protected:
377     virtual ~TaskObserver();
378   };
379
380   // These functions can only be called on the same thread that |this| is
381   // running on.
382   void AddTaskObserver(TaskObserver* task_observer);
383   void RemoveTaskObserver(TaskObserver* task_observer);
384
385   // When we go into high resolution timer mode, we will stay in hi-res mode
386   // for at least 1s.
387   static const int kHighResolutionTimerModeLeaseTimeMs = 1000;
388
389 #if defined(OS_WIN)
390   void set_os_modal_loop(bool os_modal_loop) {
391     os_modal_loop_ = os_modal_loop;
392   }
393
394   bool os_modal_loop() const {
395     return os_modal_loop_;
396   }
397 #endif  // OS_WIN
398
399   // Can only be called from the thread that owns the MessageLoop.
400   bool is_running() const;
401
402   // Returns true if the message loop has high resolution timers enabled.
403   // Provided for testing.
404   bool IsHighResolutionTimerEnabledForTesting();
405
406   // Returns true if the message loop is "idle". Provided for testing.
407   bool IsIdleForTesting();
408
409   //----------------------------------------------------------------------------
410  protected:
411
412 #if defined(OS_WIN)
413   MessagePumpWin* pump_win() {
414     return static_cast<MessagePumpWin*>(pump_.get());
415   }
416 #elif defined(OS_POSIX) && !defined(OS_IOS)
417   MessagePumpLibevent* pump_libevent() {
418     return static_cast<MessagePumpLibevent*>(pump_.get());
419   }
420 #if defined(TOOLKIT_GTK)
421   friend class MessagePumpX11;
422   MessagePumpX11* pump_gpu() {
423     DCHECK_EQ(TYPE_GPU, type());
424     return static_cast<MessagePumpX11*>(pump_.get());
425   }
426 #endif
427 #endif
428
429   scoped_ptr<MessagePump> pump_;
430
431  private:
432   friend class internal::IncomingTaskQueue;
433   friend class RunLoop;
434
435   // Configures various members for the two constructors.
436   void Init();
437
438   // Invokes the actual run loop using the message pump.
439   void RunHandler();
440
441   // Called to process any delayed non-nestable tasks.
442   bool ProcessNextDelayedNonNestableTask();
443
444   // Runs the specified PendingTask.
445   void RunTask(const PendingTask& pending_task);
446
447   // Calls RunTask or queues the pending_task on the deferred task list if it
448   // cannot be run right now.  Returns true if the task was run.
449   bool DeferOrRunPendingTask(const PendingTask& pending_task);
450
451   // Adds the pending task to delayed_work_queue_.
452   void AddToDelayedWorkQueue(const PendingTask& pending_task);
453
454   // Delete tasks that haven't run yet without running them.  Used in the
455   // destructor to make sure all the task's destructors get called.  Returns
456   // true if some work was done.
457   bool DeletePendingTasks();
458
459   // Creates a process-wide unique ID to represent this task in trace events.
460   // This will be mangled with a Process ID hash to reduce the likelyhood of
461   // colliding with MessageLoop pointers on other processes.
462   uint64 GetTaskTraceID(const PendingTask& task);
463
464   // Loads tasks from the incoming queue to |work_queue_| if the latter is
465   // empty.
466   void ReloadWorkQueue();
467
468   // Wakes up the message pump. Can be called on any thread. The caller is
469   // responsible for synchronizing ScheduleWork() calls.
470   void ScheduleWork(bool was_empty);
471
472   // Start recording histogram info about events and action IF it was enabled
473   // and IF the statistics recorder can accept a registration of our histogram.
474   void StartHistogrammer();
475
476   // Add occurrence of event to our histogram, so that we can see what is being
477   // done in a specific MessageLoop instance (i.e., specific thread).
478   // If message_histogram_ is NULL, this is a no-op.
479   void HistogramEvent(int event);
480
481   // MessagePump::Delegate methods:
482   virtual bool DoWork() OVERRIDE;
483   virtual bool DoDelayedWork(TimeTicks* next_delayed_work_time) OVERRIDE;
484   virtual bool DoIdleWork() OVERRIDE;
485   virtual void GetQueueingInformation(size_t* queue_size,
486                                       TimeDelta* queueing_delay) OVERRIDE;
487
488   const Type type_;
489
490   // A list of tasks that need to be processed by this instance.  Note that
491   // this queue is only accessed (push/pop) by our current thread.
492   TaskQueue work_queue_;
493
494   // Contains delayed tasks, sorted by their 'delayed_run_time' property.
495   DelayedTaskQueue delayed_work_queue_;
496
497   // A recent snapshot of Time::Now(), used to check delayed_work_queue_.
498   TimeTicks recent_time_;
499
500   // A queue of non-nestable tasks that we had to defer because when it came
501   // time to execute them we were in a nested message loop.  They will execute
502   // once we're out of nested message loops.
503   TaskQueue deferred_non_nestable_work_queue_;
504
505   ObserverList<DestructionObserver> destruction_observers_;
506
507   // A recursion block that prevents accidentally running additional tasks when
508   // insider a (accidentally induced?) nested message pump.
509   bool nestable_tasks_allowed_;
510
511 #if defined(OS_WIN)
512   // Should be set to true before calling Windows APIs like TrackPopupMenu, etc
513   // which enter a modal message loop.
514   bool os_modal_loop_;
515 #endif
516
517   std::string thread_name_;
518   // A profiling histogram showing the counts of various messages and events.
519   HistogramBase* message_histogram_;
520
521   RunLoop* run_loop_;
522
523   ObserverList<TaskObserver> task_observers_;
524
525   scoped_refptr<internal::IncomingTaskQueue> incoming_task_queue_;
526
527   // The message loop proxy associated with this message loop.
528   scoped_refptr<internal::MessageLoopProxyImpl> message_loop_proxy_;
529   scoped_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_;
530
531   template <class T, class R> friend class base::subtle::DeleteHelperInternal;
532   template <class T, class R> friend class base::subtle::ReleaseHelperInternal;
533
534   void DeleteSoonInternal(const tracked_objects::Location& from_here,
535                           void(*deleter)(const void*),
536                           const void* object);
537   void ReleaseSoonInternal(const tracked_objects::Location& from_here,
538                            void(*releaser)(const void*),
539                            const void* object);
540
541   DISALLOW_COPY_AND_ASSIGN(MessageLoop);
542 };
543
544 //-----------------------------------------------------------------------------
545 // MessageLoopForUI extends MessageLoop with methods that are particular to a
546 // MessageLoop instantiated with TYPE_UI.
547 //
548 // This class is typically used like so:
549 //   MessageLoopForUI::current()->...call some method...
550 //
551 class BASE_EXPORT MessageLoopForUI : public MessageLoop {
552  public:
553   MessageLoopForUI() : MessageLoop(TYPE_UI) {
554   }
555
556   // Returns the MessageLoopForUI of the current thread.
557   static MessageLoopForUI* current() {
558     MessageLoop* loop = MessageLoop::current();
559     DCHECK(loop);
560     DCHECK_EQ(MessageLoop::TYPE_UI, loop->type());
561     return static_cast<MessageLoopForUI*>(loop);
562   }
563
564   static bool IsCurrent() {
565     MessageLoop* loop = MessageLoop::current();
566     return loop && loop->type() == MessageLoop::TYPE_UI;
567   }
568
569 #if defined(OS_IOS)
570   // On iOS, the main message loop cannot be Run().  Instead call Attach(),
571   // which connects this MessageLoop to the UI thread's CFRunLoop and allows
572   // PostTask() to work.
573   void Attach();
574 #endif
575
576 #if defined(OS_ANDROID)
577   // On Android, the UI message loop is handled by Java side. So Run() should
578   // never be called. Instead use Start(), which will forward all the native UI
579   // events to the Java message loop.
580   void Start();
581 #endif
582
583 #if !defined(OS_NACL) && (defined(TOOLKIT_GTK) || defined(USE_OZONE) || \
584                           defined(OS_WIN) || defined(USE_X11))
585   // Please see message_pump_win/message_pump_glib for definitions of these
586   // methods.
587   void AddObserver(Observer* observer);
588   void RemoveObserver(Observer* observer);
589 #endif
590
591  protected:
592 #if defined(USE_X11)
593   friend class MessagePumpX11;
594 #endif
595 #if defined(USE_OZONE) && !defined(OS_NACL)
596   friend class MessagePumpOzone;
597 #endif
598
599 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
600   // TODO(rvargas): Make this platform independent.
601   MessagePumpForUI* pump_ui() {
602     return static_cast<MessagePumpForUI*>(pump_.get());
603   }
604 #endif
605 };
606
607 // Do not add any member variables to MessageLoopForUI!  This is important b/c
608 // MessageLoopForUI is often allocated via MessageLoop(TYPE_UI).  Any extra
609 // data that you need should be stored on the MessageLoop's pump_ instance.
610 COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForUI),
611                MessageLoopForUI_should_not_have_extra_member_variables);
612
613 //-----------------------------------------------------------------------------
614 // MessageLoopForIO extends MessageLoop with methods that are particular to a
615 // MessageLoop instantiated with TYPE_IO.
616 //
617 // This class is typically used like so:
618 //   MessageLoopForIO::current()->...call some method...
619 //
620 class BASE_EXPORT MessageLoopForIO : public MessageLoop {
621  public:
622 #if defined(OS_WIN)
623   typedef MessagePumpForIO::IOHandler IOHandler;
624   typedef MessagePumpForIO::IOContext IOContext;
625   typedef MessagePumpForIO::IOObserver IOObserver;
626 #elif defined(OS_IOS)
627   typedef MessagePumpIOSForIO::Watcher Watcher;
628   typedef MessagePumpIOSForIO::FileDescriptorWatcher
629       FileDescriptorWatcher;
630   typedef MessagePumpIOSForIO::IOObserver IOObserver;
631
632   enum Mode {
633     WATCH_READ = MessagePumpIOSForIO::WATCH_READ,
634     WATCH_WRITE = MessagePumpIOSForIO::WATCH_WRITE,
635     WATCH_READ_WRITE = MessagePumpIOSForIO::WATCH_READ_WRITE
636   };
637 #elif defined(OS_POSIX)
638   typedef MessagePumpLibevent::Watcher Watcher;
639   typedef MessagePumpLibevent::FileDescriptorWatcher
640       FileDescriptorWatcher;
641   typedef MessagePumpLibevent::IOObserver IOObserver;
642
643   enum Mode {
644     WATCH_READ = MessagePumpLibevent::WATCH_READ,
645     WATCH_WRITE = MessagePumpLibevent::WATCH_WRITE,
646     WATCH_READ_WRITE = MessagePumpLibevent::WATCH_READ_WRITE
647   };
648
649 #endif
650
651   MessageLoopForIO() : MessageLoop(TYPE_IO) {
652   }
653
654   // Returns the MessageLoopForIO of the current thread.
655   static MessageLoopForIO* current() {
656     MessageLoop* loop = MessageLoop::current();
657     DCHECK_EQ(MessageLoop::TYPE_IO, loop->type());
658     return static_cast<MessageLoopForIO*>(loop);
659   }
660
661   static bool IsCurrent() {
662     MessageLoop* loop = MessageLoop::current();
663     return loop && loop->type() == MessageLoop::TYPE_IO;
664   }
665
666   void AddIOObserver(IOObserver* io_observer) {
667     pump_io()->AddIOObserver(io_observer);
668   }
669
670   void RemoveIOObserver(IOObserver* io_observer) {
671     pump_io()->RemoveIOObserver(io_observer);
672   }
673
674 #if defined(OS_WIN)
675   // Please see MessagePumpWin for definitions of these methods.
676   void RegisterIOHandler(HANDLE file, IOHandler* handler);
677   bool RegisterJobObject(HANDLE job, IOHandler* handler);
678   bool WaitForIOCompletion(DWORD timeout, IOHandler* filter);
679
680  protected:
681   // TODO(rvargas): Make this platform independent.
682   MessagePumpForIO* pump_io() {
683     return static_cast<MessagePumpForIO*>(pump_.get());
684   }
685
686 #elif defined(OS_IOS)
687   // Please see MessagePumpIOSForIO for definition.
688   bool WatchFileDescriptor(int fd,
689                            bool persistent,
690                            Mode mode,
691                            FileDescriptorWatcher *controller,
692                            Watcher *delegate);
693
694  private:
695   MessagePumpIOSForIO* pump_io() {
696     return static_cast<MessagePumpIOSForIO*>(pump_.get());
697   }
698
699 #elif defined(OS_POSIX)
700   // Please see MessagePumpLibevent for definition.
701   bool WatchFileDescriptor(int fd,
702                            bool persistent,
703                            Mode mode,
704                            FileDescriptorWatcher* controller,
705                            Watcher* delegate);
706
707  private:
708   MessagePumpLibevent* pump_io() {
709     return static_cast<MessagePumpLibevent*>(pump_.get());
710   }
711 #endif  // defined(OS_POSIX)
712 };
713
714 // Do not add any member variables to MessageLoopForIO!  This is important b/c
715 // MessageLoopForIO is often allocated via MessageLoop(TYPE_IO).  Any extra
716 // data that you need should be stored on the MessageLoop's pump_ instance.
717 COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO),
718                MessageLoopForIO_should_not_have_extra_member_variables);
719
720 }  // namespace base
721
722 #endif  // BASE_MESSAGE_LOOP_MESSAGE_LOOP_H_