ipc/chromium/src/base/message_loop.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/chromium/src/base/message_loop.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,569 @@
     1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
     1.5 +// Use of this source code is governed by a BSD-style license that can be
     1.6 +// found in the LICENSE file.
     1.7 +
     1.8 +#ifndef BASE_MESSAGE_LOOP_H_
     1.9 +#define BASE_MESSAGE_LOOP_H_
    1.10 +
    1.11 +#include <deque>
    1.12 +#include <queue>
    1.13 +#include <string>
    1.14 +#include <vector>
    1.15 +
    1.16 +#include <map>
    1.17 +#include "base/lock.h"
    1.18 +#include "base/message_pump.h"
    1.19 +#include "base/observer_list.h"
    1.20 +#include "base/ref_counted.h"
    1.21 +#include "base/scoped_ptr.h"
    1.22 +#include "base/task.h"
    1.23 +#include "base/timer.h"
    1.24 +
    1.25 +#if defined(OS_WIN)
    1.26 +// We need this to declare base::MessagePumpWin::Dispatcher, which we should
    1.27 +// really just eliminate.
    1.28 +#include "base/message_pump_win.h"
    1.29 +#elif defined(OS_POSIX)
    1.30 +#include "base/message_pump_libevent.h"
    1.31 +#endif
    1.32 +
    1.33 +namespace mozilla {
    1.34 +namespace ipc {
    1.35 +
    1.36 +class DoWorkRunnable;
    1.37 +
    1.38 +} /* namespace ipc */
    1.39 +} /* namespace mozilla */
    1.40 +
    1.41 +// A MessageLoop is used to process events for a particular thread.  There is
    1.42 +// at most one MessageLoop instance per thread.
    1.43 +//
    1.44 +// Events include at a minimum Task instances submitted to PostTask or those
    1.45 +// managed by TimerManager.  Depending on the type of message pump used by the
    1.46 +// MessageLoop other events such as UI messages may be processed.  On Windows
    1.47 +// APC calls (as time permits) and signals sent to a registered set of HANDLEs
    1.48 +// may also be processed.
    1.49 +//
    1.50 +// NOTE: Unless otherwise specified, a MessageLoop's methods may only be called
    1.51 +// on the thread where the MessageLoop's Run method executes.
    1.52 +//
    1.53 +// NOTE: MessageLoop has task reentrancy protection.  This means that if a
    1.54 +// task is being processed, a second task cannot start until the first task is
    1.55 +// finished.  Reentrancy can happen when processing a task, and an inner
    1.56 +// message pump is created.  That inner pump then processes native messages
    1.57 +// which could implicitly start an inner task.  Inner message pumps are created
    1.58 +// with dialogs (DialogBox), common dialogs (GetOpenFileName), OLE functions
    1.59 +// (DoDragDrop), printer functions (StartDoc) and *many* others.
    1.60 +//
    1.61 +// Sample workaround when inner task processing is needed:
    1.62 +//   bool old_state = MessageLoop::current()->NestableTasksAllowed();
    1.63 +//   MessageLoop::current()->SetNestableTasksAllowed(true);
    1.64 +//   HRESULT hr = DoDragDrop(...); // Implicitly runs a modal message loop here.
    1.65 +//   MessageLoop::current()->SetNestableTasksAllowed(old_state);
    1.66 +//   // Process hr  (the result returned by DoDragDrop().
    1.67 +//
    1.68 +// Please be SURE your task is reentrant (nestable) and all global variables
    1.69 +// are stable and accessible before calling SetNestableTasksAllowed(true).
    1.70 +//
    1.71 +class MessageLoop : public base::MessagePump::Delegate {
    1.72 +
    1.73 +  friend class mozilla::ipc::DoWorkRunnable;
    1.74 +
    1.75 +public:
    1.76 +  // A DestructionObserver is notified when the current MessageLoop is being
    1.77 +  // destroyed.  These obsevers are notified prior to MessageLoop::current()
    1.78 +  // being changed to return NULL.  This gives interested parties the chance to
    1.79 +  // do final cleanup that depends on the MessageLoop.
    1.80 +  //
    1.81 +  // NOTE: Any tasks posted to the MessageLoop during this notification will
    1.82 +  // not be run.  Instead, they will be deleted.
    1.83 +  //
    1.84 +  class DestructionObserver {
    1.85 +   public:
    1.86 +    virtual ~DestructionObserver() {}
    1.87 +    virtual void WillDestroyCurrentMessageLoop() = 0;
    1.88 +  };
    1.89 +
    1.90 +  // Add a DestructionObserver, which will start receiving notifications
    1.91 +  // immediately.
    1.92 +  void AddDestructionObserver(DestructionObserver* destruction_observer);
    1.93 +
    1.94 +  // Remove a DestructionObserver.  It is safe to call this method while a
    1.95 +  // DestructionObserver is receiving a notification callback.
    1.96 +  void RemoveDestructionObserver(DestructionObserver* destruction_observer);
    1.97 +
    1.98 +  // The "PostTask" family of methods call the task's Run method asynchronously
    1.99 +  // from within a message loop at some point in the future.
   1.100 +  //
   1.101 +  // With the PostTask variant, tasks are invoked in FIFO order, inter-mixed
   1.102 +  // with normal UI or IO event processing.  With the PostDelayedTask variant,
   1.103 +  // tasks are called after at least approximately 'delay_ms' have elapsed.
   1.104 +  //
   1.105 +  // The NonNestable variants work similarly except that they promise never to
   1.106 +  // dispatch the task from a nested invocation of MessageLoop::Run.  Instead,
   1.107 +  // such tasks get deferred until the top-most MessageLoop::Run is executing.
   1.108 +  //
   1.109 +  // The MessageLoop takes ownership of the Task, and deletes it after it has
   1.110 +  // been Run().
   1.111 +  //
   1.112 +  // NOTE: These methods may be called on any thread.  The Task will be invoked
   1.113 +  // on the thread that executes MessageLoop::Run().
   1.114 +
   1.115 +  void PostTask(
   1.116 +      const tracked_objects::Location& from_here, Task* task);
   1.117 +
   1.118 +  void PostDelayedTask(
   1.119 +      const tracked_objects::Location& from_here, Task* task, int delay_ms);
   1.120 +
   1.121 +  void PostNonNestableTask(
   1.122 +      const tracked_objects::Location& from_here, Task* task);
   1.123 +
   1.124 +  void PostNonNestableDelayedTask(
   1.125 +      const tracked_objects::Location& from_here, Task* task, int delay_ms);
   1.126 +
   1.127 +  // PostIdleTask is not thread safe and should be called on this thread
   1.128 +  void PostIdleTask(
   1.129 +      const tracked_objects::Location& from_here, Task* task);
   1.130 +
   1.131 +  // A variant on PostTask that deletes the given object.  This is useful
   1.132 +  // if the object needs to live until the next run of the MessageLoop (for
   1.133 +  // example, deleting a RenderProcessHost from within an IPC callback is not
   1.134 +  // good).
   1.135 +  //
   1.136 +  // NOTE: This method may be called on any thread.  The object will be deleted
   1.137 +  // on the thread that executes MessageLoop::Run().  If this is not the same
   1.138 +  // as the thread that calls PostDelayedTask(FROM_HERE, ), then T MUST inherit
   1.139 +  // from RefCountedThreadSafe<T>!
   1.140 +  template <class T>
   1.141 +  void DeleteSoon(const tracked_objects::Location& from_here, T* object) {
   1.142 +    PostNonNestableTask(from_here, new DeleteTask<T>(object));
   1.143 +  }
   1.144 +
   1.145 +  // A variant on PostTask that releases the given reference counted object
   1.146 +  // (by calling its Release method).  This is useful if the object needs to
   1.147 +  // live until the next run of the MessageLoop, or if the object needs to be
   1.148 +  // released on a particular thread.
   1.149 +  //
   1.150 +  // NOTE: This method may be called on any thread.  The object will be
   1.151 +  // released (and thus possibly deleted) on the thread that executes
   1.152 +  // MessageLoop::Run().  If this is not the same as the thread that calls
   1.153 +  // PostDelayedTask(FROM_HERE, ), then T MUST inherit from
   1.154 +  // RefCountedThreadSafe<T>!
   1.155 +  template <class T>
   1.156 +  void ReleaseSoon(const tracked_objects::Location& from_here, T* object) {
   1.157 +    PostNonNestableTask(from_here, new ReleaseTask<T>(object));
   1.158 +  }
   1.159 +
   1.160 +  // Run the message loop.
   1.161 +  void Run();
   1.162 +
   1.163 +  // Process all pending tasks, windows messages, etc., but don't wait/sleep.
   1.164 +  // Return as soon as all items that can be run are taken care of.
   1.165 +  void RunAllPending();
   1.166 +
   1.167 +  // Signals the Run method to return after it is done processing all pending
   1.168 +  // messages.  This method may only be called on the same thread that called
   1.169 +  // Run, and Run must still be on the call stack.
   1.170 +  //
   1.171 +  // Use QuitTask if you need to Quit another thread's MessageLoop, but note
   1.172 +  // that doing so is fairly dangerous if the target thread makes nested calls
   1.173 +  // to MessageLoop::Run.  The problem being that you won't know which nested
   1.174 +  // run loop you are quiting, so be careful!
   1.175 +  //
   1.176 +  void Quit();
   1.177 +
   1.178 +  // Invokes Quit on the current MessageLoop when run.  Useful to schedule an
   1.179 +  // arbitrary MessageLoop to Quit.
   1.180 +  class QuitTask : public Task {
   1.181 +   public:
   1.182 +    virtual void Run() {
   1.183 +      MessageLoop::current()->Quit();
   1.184 +    }
   1.185 +  };
   1.186 +
   1.187 +  // A MessageLoop has a particular type, which indicates the set of
   1.188 +  // asynchronous events it may process in addition to tasks and timers.
   1.189 +  //
   1.190 +  // TYPE_DEFAULT
   1.191 +  //   This type of ML only supports tasks and timers.
   1.192 +  //
   1.193 +  // TYPE_UI
   1.194 +  //   This type of ML also supports native UI events (e.g., Windows messages).
   1.195 +  //   See also MessageLoopForUI.
   1.196 +  //
   1.197 +  // TYPE_IO
   1.198 +  //   This type of ML also supports asynchronous IO.  See also
   1.199 +  //   MessageLoopForIO.
   1.200 +  //
   1.201 +  // TYPE_MOZILLA_CHILD
   1.202 +  //   This type of ML is used in Mozilla child processes which initialize
   1.203 +  //   XPCOM and use the gecko event loop.
   1.204 +  //
   1.205 +  // TYPE_MOZILLA_UI
   1.206 +  //   This type of ML is used in Mozilla parent processes which initialize
   1.207 +  //   XPCOM and use the gecko event loop.
   1.208 +  //
   1.209 +  // TYPE_MOZILLA_NONMAINTHREAD
   1.210 +  //   This type of ML is used in Mozilla parent processes which initialize
   1.211 +  //   XPCOM and use the nsThread event loop.
   1.212 +  //
   1.213 +  enum Type {
   1.214 +    TYPE_DEFAULT,
   1.215 +    TYPE_UI,
   1.216 +    TYPE_IO,
   1.217 +    TYPE_MOZILLA_CHILD,
   1.218 +    TYPE_MOZILLA_UI,
   1.219 +    TYPE_MOZILLA_NONMAINTHREAD
   1.220 +  };
   1.221 +
   1.222 +  // Normally, it is not necessary to instantiate a MessageLoop.  Instead, it
   1.223 +  // is typical to make use of the current thread's MessageLoop instance.
   1.224 +  explicit MessageLoop(Type type = TYPE_DEFAULT);
   1.225 +  ~MessageLoop();
   1.226 +
   1.227 +  // Returns the type passed to the constructor.
   1.228 +  Type type() const { return type_; }
   1.229 +
   1.230 +  // Unique, non-repeating ID for this message loop.
   1.231 +  int32_t id() const { return id_; }
   1.232 +
   1.233 +  // Optional call to connect the thread name with this loop.
   1.234 +  void set_thread_name(const std::string& thread_name) {
   1.235 +    DCHECK(thread_name_.empty()) << "Should not rename this thread!";
   1.236 +    thread_name_ = thread_name;
   1.237 +  }
   1.238 +  const std::string& thread_name() const { return thread_name_; }
   1.239 +
   1.240 +  // Returns the MessageLoop object for the current thread, or null if none.
   1.241 +  static MessageLoop* current();
   1.242 +
   1.243 +  // Enables or disables the recursive task processing. This happens in the case
   1.244 +  // of recursive message loops. Some unwanted message loop may occurs when
   1.245 +  // using common controls or printer functions. By default, recursive task
   1.246 +  // processing is disabled.
   1.247 +  //
   1.248 +  // The specific case where tasks get queued is:
   1.249 +  // - The thread is running a message loop.
   1.250 +  // - It receives a task #1 and execute it.
   1.251 +  // - The task #1 implicitly start a message loop, like a MessageBox in the
   1.252 +  //   unit test. This can also be StartDoc or GetSaveFileName.
   1.253 +  // - The thread receives a task #2 before or while in this second message
   1.254 +  //   loop.
   1.255 +  // - With NestableTasksAllowed set to true, the task #2 will run right away.
   1.256 +  //   Otherwise, it will get executed right after task #1 completes at "thread
   1.257 +  //   message loop level".
   1.258 +  void SetNestableTasksAllowed(bool allowed);
   1.259 +  void ScheduleWork();
   1.260 +  bool NestableTasksAllowed() const;
   1.261 +
   1.262 +  // Enables or disables the restoration during an exception of the unhandled
   1.263 +  // exception filter that was active when Run() was called. This can happen
   1.264 +  // if some third party code call SetUnhandledExceptionFilter() and never
   1.265 +  // restores the previous filter.
   1.266 +  void set_exception_restoration(bool restore) {
   1.267 +    exception_restoration_ = restore;
   1.268 +  }
   1.269 +
   1.270 +#if defined(OS_WIN)
   1.271 +  void set_os_modal_loop(bool os_modal_loop) {
   1.272 +    os_modal_loop_ = os_modal_loop;
   1.273 +  }
   1.274 +
   1.275 +  bool & os_modal_loop() {
   1.276 +    return os_modal_loop_;
   1.277 +  }
   1.278 +#endif  // OS_WIN
   1.279 +
   1.280 +  // Set the timeouts for background hang monitoring.
   1.281 +  // A value of 0 indicates there is no timeout.
   1.282 +  void set_hang_timeouts(uint32_t transient_timeout_ms,
   1.283 +                         uint32_t permanent_timeout_ms) {
   1.284 +    transient_hang_timeout_ = transient_timeout_ms;
   1.285 +    permanent_hang_timeout_ = permanent_timeout_ms;
   1.286 +  }
   1.287 +  uint32_t transient_hang_timeout() const {
   1.288 +    return transient_hang_timeout_;
   1.289 +  }
   1.290 +  uint32_t permanent_hang_timeout() const {
   1.291 +    return permanent_hang_timeout_;
   1.292 +  }
   1.293 +
   1.294 +  //----------------------------------------------------------------------------
   1.295 + protected:
   1.296 +  struct RunState {
   1.297 +    // Used to count how many Run() invocations are on the stack.
   1.298 +    int run_depth;
   1.299 +
   1.300 +    // Used to record that Quit() was called, or that we should quit the pump
   1.301 +    // once it becomes idle.
   1.302 +    bool quit_received;
   1.303 +
   1.304 +#if defined(OS_WIN)
   1.305 +    base::MessagePumpWin::Dispatcher* dispatcher;
   1.306 +#endif
   1.307 +  };
   1.308 +
   1.309 +  class AutoRunState : RunState {
   1.310 +   public:
   1.311 +    explicit AutoRunState(MessageLoop* loop);
   1.312 +    ~AutoRunState();
   1.313 +   private:
   1.314 +    MessageLoop* loop_;
   1.315 +    RunState* previous_state_;
   1.316 +  };
   1.317 +
   1.318 +  // This structure is copied around by value.
   1.319 +  struct PendingTask {
   1.320 +    Task* task;                        // The task to run.
   1.321 +    base::TimeTicks delayed_run_time;  // The time when the task should be run.
   1.322 +    int sequence_num;                  // Secondary sort key for run time.
   1.323 +    bool nestable;                     // OK to dispatch from a nested loop.
   1.324 +
   1.325 +    PendingTask(Task* task, bool nestable)
   1.326 +        : task(task), sequence_num(0), nestable(nestable) {
   1.327 +    }
   1.328 +
   1.329 +    // Used to support sorting.
   1.330 +    bool operator<(const PendingTask& other) const;
   1.331 +  };
   1.332 +
   1.333 +  typedef std::queue<PendingTask> TaskQueue;
   1.334 +  typedef std::priority_queue<PendingTask> DelayedTaskQueue;
   1.335 +
   1.336 +#if defined(OS_WIN)
   1.337 +  base::MessagePumpWin* pump_win() {
   1.338 +    return static_cast<base::MessagePumpWin*>(pump_.get());
   1.339 +  }
   1.340 +#elif defined(OS_POSIX)
   1.341 +  base::MessagePumpLibevent* pump_libevent() {
   1.342 +    return static_cast<base::MessagePumpLibevent*>(pump_.get());
   1.343 +  }
   1.344 +#endif
   1.345 +
   1.346 +  // A function to encapsulate all the exception handling capability in the
   1.347 +  // stacks around the running of a main message loop.  It will run the message
   1.348 +  // loop in a SEH try block or not depending on the set_SEH_restoration()
   1.349 +  // flag.
   1.350 +  void RunHandler();
   1.351 +
   1.352 +  // A surrounding stack frame around the running of the message loop that
   1.353 +  // supports all saving and restoring of state, as is needed for any/all (ugly)
   1.354 +  // recursive calls.
   1.355 +  void RunInternal();
   1.356 +
   1.357 +  // Called to process any delayed non-nestable tasks.
   1.358 +  bool ProcessNextDelayedNonNestableTask();
   1.359 +
   1.360 +  //----------------------------------------------------------------------------
   1.361 +  // Run a work_queue_ task or new_task, and delete it (if it was processed by
   1.362 +  // PostTask). If there are queued tasks, the oldest one is executed and
   1.363 +  // new_task is queued. new_task is optional and can be NULL. In this NULL
   1.364 +  // case, the method will run one pending task (if any exist). Returns true if
   1.365 +  // it executes a task.  Queued tasks accumulate only when there is a
   1.366 +  // non-nestable task currently processing, in which case the new_task is
   1.367 +  // appended to the list work_queue_.  Such re-entrancy generally happens when
   1.368 +  // an unrequested message pump (typical of a native dialog) is executing in
   1.369 +  // the context of a task.
   1.370 +  bool QueueOrRunTask(Task* new_task);
   1.371 +
   1.372 +  // Runs the specified task and deletes it.
   1.373 +  void RunTask(Task* task);
   1.374 +
   1.375 +  // Calls RunTask or queues the pending_task on the deferred task list if it
   1.376 +  // cannot be run right now.  Returns true if the task was run.
   1.377 +  bool DeferOrRunPendingTask(const PendingTask& pending_task);
   1.378 +
   1.379 +  // Adds the pending task to delayed_work_queue_.
   1.380 +  void AddToDelayedWorkQueue(const PendingTask& pending_task);
   1.381 +
   1.382 +  // Load tasks from the incoming_queue_ into work_queue_ if the latter is
   1.383 +  // empty.  The former requires a lock to access, while the latter is directly
   1.384 +  // accessible on this thread.
   1.385 +  void ReloadWorkQueue();
   1.386 +
   1.387 +  // Delete tasks that haven't run yet without running them.  Used in the
   1.388 +  // destructor to make sure all the task's destructors get called.  Returns
   1.389 +  // true if some work was done.
   1.390 +  bool DeletePendingTasks();
   1.391 +
   1.392 +  // Post a task to our incomming queue.
   1.393 +  void PostTask_Helper(const tracked_objects::Location& from_here, Task* task,
   1.394 +                       int delay_ms, bool nestable);
   1.395 +
   1.396 +  // base::MessagePump::Delegate methods:
   1.397 +  virtual bool DoWork();
   1.398 +  virtual bool DoDelayedWork(base::TimeTicks* next_delayed_work_time);
   1.399 +  virtual bool DoIdleWork();
   1.400 +
   1.401 +  Type type_;
   1.402 +  int32_t id_;
   1.403 +
   1.404 +  // A list of tasks that need to be processed by this instance.  Note that
   1.405 +  // this queue is only accessed (push/pop) by our current thread.
   1.406 +  TaskQueue work_queue_;
   1.407 +
   1.408 +  // Contains delayed tasks, sorted by their 'delayed_run_time' property.
   1.409 +  DelayedTaskQueue delayed_work_queue_;
   1.410 +
   1.411 +  // A queue of non-nestable tasks that we had to defer because when it came
   1.412 +  // time to execute them we were in a nested message loop.  They will execute
   1.413 +  // once we're out of nested message loops.
   1.414 +  TaskQueue deferred_non_nestable_work_queue_;
   1.415 +
   1.416 +  scoped_refptr<base::MessagePump> pump_;
   1.417 +
   1.418 +  base::ObserverList<DestructionObserver> destruction_observers_;
   1.419 +
   1.420 +  // A recursion block that prevents accidentally running additonal tasks when
   1.421 +  // insider a (accidentally induced?) nested message pump.
   1.422 +  bool nestable_tasks_allowed_;
   1.423 +
   1.424 +  bool exception_restoration_;
   1.425 +
   1.426 +  std::string thread_name_;
   1.427 +
   1.428 +  // A null terminated list which creates an incoming_queue of tasks that are
   1.429 +  // aquired under a mutex for processing on this instance's thread. These tasks
   1.430 +  // have not yet been sorted out into items for our work_queue_ vs items that
   1.431 +  // will be handled by the TimerManager.
   1.432 +  TaskQueue incoming_queue_;
   1.433 +  // Protect access to incoming_queue_.
   1.434 +  Lock incoming_queue_lock_;
   1.435 +
   1.436 +  RunState* state_;
   1.437 +  int run_depth_base_;
   1.438 +
   1.439 +#if defined(OS_WIN)
   1.440 +  // Should be set to true before calling Windows APIs like TrackPopupMenu, etc
   1.441 +  // which enter a modal message loop.
   1.442 +  bool os_modal_loop_;
   1.443 +#endif
   1.444 +
   1.445 +  // Timeout values for hang monitoring
   1.446 +  uint32_t transient_hang_timeout_;
   1.447 +  uint32_t permanent_hang_timeout_;
   1.448 +
   1.449 +  // The next sequence number to use for delayed tasks.
   1.450 +  int next_sequence_num_;
   1.451 +
   1.452 +  DISALLOW_COPY_AND_ASSIGN(MessageLoop);
   1.453 +};
   1.454 +
   1.455 +//-----------------------------------------------------------------------------
   1.456 +// MessageLoopForUI extends MessageLoop with methods that are particular to a
   1.457 +// MessageLoop instantiated with TYPE_UI.
   1.458 +//
   1.459 +// This class is typically used like so:
   1.460 +//   MessageLoopForUI::current()->...call some method...
   1.461 +//
   1.462 +class MessageLoopForUI : public MessageLoop {
   1.463 + public:
   1.464 +  MessageLoopForUI(Type type=TYPE_UI) : MessageLoop(type) {
   1.465 +  }
   1.466 +
   1.467 +  // Returns the MessageLoopForUI of the current thread.
   1.468 +  static MessageLoopForUI* current() {
   1.469 +    MessageLoop* loop = MessageLoop::current();
   1.470 +    if (!loop)
   1.471 +      return NULL;
   1.472 +    Type type = loop->type();
   1.473 +    DCHECK(type == MessageLoop::TYPE_UI ||
   1.474 +           type == MessageLoop::TYPE_MOZILLA_UI ||
   1.475 +           type == MessageLoop::TYPE_MOZILLA_CHILD);
   1.476 +    return static_cast<MessageLoopForUI*>(loop);
   1.477 +  }
   1.478 +
   1.479 +#if defined(OS_WIN)
   1.480 +  typedef base::MessagePumpWin::Dispatcher Dispatcher;
   1.481 +  typedef base::MessagePumpWin::Observer Observer;
   1.482 +
   1.483 +  // Please see MessagePumpWin for definitions of these methods.
   1.484 +  void Run(Dispatcher* dispatcher);
   1.485 +  void AddObserver(Observer* observer);
   1.486 +  void RemoveObserver(Observer* observer);
   1.487 +  void WillProcessMessage(const MSG& message);
   1.488 +  void DidProcessMessage(const MSG& message);
   1.489 +  void PumpOutPendingPaintMessages();
   1.490 +
   1.491 + protected:
   1.492 +  // TODO(rvargas): Make this platform independent.
   1.493 +  base::MessagePumpForUI* pump_ui() {
   1.494 +    return static_cast<base::MessagePumpForUI*>(pump_.get());
   1.495 +  }
   1.496 +#endif  // defined(OS_WIN)
   1.497 +};
   1.498 +
   1.499 +// Do not add any member variables to MessageLoopForUI!  This is important b/c
   1.500 +// MessageLoopForUI is often allocated via MessageLoop(TYPE_UI).  Any extra
   1.501 +// data that you need should be stored on the MessageLoop's pump_ instance.
   1.502 +COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForUI),
   1.503 +               MessageLoopForUI_should_not_have_extra_member_variables);
   1.504 +
   1.505 +//-----------------------------------------------------------------------------
   1.506 +// MessageLoopForIO extends MessageLoop with methods that are particular to a
   1.507 +// MessageLoop instantiated with TYPE_IO.
   1.508 +//
   1.509 +// This class is typically used like so:
   1.510 +//   MessageLoopForIO::current()->...call some method...
   1.511 +//
   1.512 +class MessageLoopForIO : public MessageLoop {
   1.513 + public:
   1.514 +  MessageLoopForIO() : MessageLoop(TYPE_IO) {
   1.515 +  }
   1.516 +
   1.517 +  // Returns the MessageLoopForIO of the current thread.
   1.518 +  static MessageLoopForIO* current() {
   1.519 +    MessageLoop* loop = MessageLoop::current();
   1.520 +    DCHECK_EQ(MessageLoop::TYPE_IO, loop->type());
   1.521 +    return static_cast<MessageLoopForIO*>(loop);
   1.522 +  }
   1.523 +
   1.524 +#if defined(OS_WIN)
   1.525 +  typedef base::MessagePumpForIO::IOHandler IOHandler;
   1.526 +  typedef base::MessagePumpForIO::IOContext IOContext;
   1.527 +
   1.528 +  // Please see MessagePumpWin for definitions of these methods.
   1.529 +  void RegisterIOHandler(HANDLE file_handle, IOHandler* handler);
   1.530 +  bool WaitForIOCompletion(DWORD timeout, IOHandler* filter);
   1.531 +
   1.532 + protected:
   1.533 +  // TODO(rvargas): Make this platform independent.
   1.534 +  base::MessagePumpForIO* pump_io() {
   1.535 +    return static_cast<base::MessagePumpForIO*>(pump_.get());
   1.536 +  }
   1.537 +
   1.538 +#elif defined(OS_POSIX)
   1.539 +  typedef base::MessagePumpLibevent::Watcher Watcher;
   1.540 +  typedef base::MessagePumpLibevent::FileDescriptorWatcher
   1.541 +      FileDescriptorWatcher;
   1.542 +  typedef base::LineWatcher LineWatcher;
   1.543 +
   1.544 +  enum Mode {
   1.545 +    WATCH_READ = base::MessagePumpLibevent::WATCH_READ,
   1.546 +    WATCH_WRITE = base::MessagePumpLibevent::WATCH_WRITE,
   1.547 +    WATCH_READ_WRITE = base::MessagePumpLibevent::WATCH_READ_WRITE
   1.548 +  };
   1.549 +
   1.550 +  // Please see MessagePumpLibevent for definition.
   1.551 +  bool WatchFileDescriptor(int fd,
   1.552 +                           bool persistent,
   1.553 +                           Mode mode,
   1.554 +                           FileDescriptorWatcher *controller,
   1.555 +                           Watcher *delegate);
   1.556 +
   1.557 +  typedef base::MessagePumpLibevent::SignalEvent SignalEvent;
   1.558 +  typedef base::MessagePumpLibevent::SignalWatcher SignalWatcher;
   1.559 +  bool CatchSignal(int sig,
   1.560 +                   SignalEvent* sigevent,
   1.561 +                   SignalWatcher* delegate);
   1.562 +
   1.563 +#endif  // defined(OS_POSIX)
   1.564 +};
   1.565 +
   1.566 +// Do not add any member variables to MessageLoopForIO!  This is important b/c
   1.567 +// MessageLoopForIO is often allocated via MessageLoop(TYPE_IO).  Any extra
   1.568 +// data that you need should be stored on the MessageLoop's pump_ instance.
   1.569 +COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO),
   1.570 +               MessageLoopForIO_should_not_have_extra_member_variables);
   1.571 +
   1.572 +#endif  // BASE_MESSAGE_LOOP_H_

mercurial