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