LCOV - code coverage report
Current view: top level - ipc/chromium/src/base - message_loop.h (source / functions) Hit Total Coverage
Test: output.info Lines: 45 55 81.8 %
Date: 2017-07-14 16:53:18 Functions: 17 26 65.4 %
Legend: Lines: hit not hit

          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_

Generated by: LCOV version 1.13