15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_
67d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_pump.h"
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_pump_dispatcher.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessagePumpWin serves as the base for specialized versions of the MessagePump
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for Windows. It provides basic functionality like handling of observers and
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// controlling the lifetime of the message pump.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT MessagePumpWin : public MessagePump {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessagePumpWin() : have_work_(0), state_(NULL) {}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MessagePumpWin() {}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Like MessagePump::Run, but MSG objects are routed through dispatcher.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunWithDispatcher(Delegate* delegate, MessagePumpDispatcher* dispatcher);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MessagePump methods:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Run(Delegate* delegate) { RunWithDispatcher(delegate, NULL); }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Quit();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct RunState {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Delegate* delegate;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessagePumpDispatcher* dispatcher;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Used to flag that the current Run() invocation should return ASAP.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool should_quit;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Used to count how many Run() invocations are on the stack.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int run_depth;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DoRunLoop() = 0;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int GetCurrentDelay() const;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The time at which delayed work should run.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeTicks delayed_work_time_;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A boolean value used to indicate if there is a kMsgDoWork message pending
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the Windows Message queue.  There is at most one such message, and it
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can drive execution of tasks when a native message pump is running.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LONG have_work_;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // State for the current invocation of Run.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunState* state_;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessagePumpForUI extends MessagePumpWin with methods that are particular to a
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessageLoop instantiated with TYPE_UI.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessagePumpForUI implements a "traditional" Windows message pump. It contains
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a nearly infinite loop that peeks out messages, and then dispatches them.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Intermixed with those peeks are callouts to DoWork for pending tasks, and
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DoDelayedWork for pending timers. When there are no events to be serviced,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this pump goes into a wait state. In most cases, this message pump handles
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// all processing.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// However, when a task, or windows event, invokes on the stack a native dialog
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// box or such, that window typically provides a bare bones (native?) message
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pump.  That bare-bones message pump generally supports little more than a
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// peek of the Windows message queue, followed by a dispatch of the peeked
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// message.  MessageLoop extends that bare-bones message pump to also service
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tasks, at the cost of some complexity.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The basic structure of the extension (refered to as a sub-pump) is that a
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// special message, kMsgHaveWork, is repeatedly injected into the Windows
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Message queue.  Each time the kMsgHaveWork message is peeked, checks are
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// made for an extended set of events, including the availability of Tasks to
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// run.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// After running a task, the special message kMsgHaveWork is again posted to
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the Windows Message queue, ensuring a future time slice for processing a
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// future event.  To prevent flooding the Windows Message queue, care is taken
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be sure that at most one kMsgHaveWork message is EVER pending in the
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Window's Message queue.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// There are a few additional complexities in this system where, when there are
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// no Tasks to run, this otherwise infinite stream of messages which drives the
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sub-pump is halted.  The pump is automatically re-started when Tasks are
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// queued.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A second complexity is that the presence of this stream of posted tasks may
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// prevent a bare-bones message pump from ever peeking a WM_PAINT or WM_TIMER.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Such paint and timer events always give priority to a posted message, such as
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kMsgHaveWork messages.  As a result, care is taken to do some peeking in
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// between the posting of each kMsgHaveWork message (i.e., after kMsgHaveWork
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is peeked, and before a replacement kMsgHaveWork is posted).
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: Although it may seem odd that messages are used to start and stop this
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// flow (as opposed to signaling objects, etc.), it should be understood that
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the native message pump will *only* respond to messages.  As a result, it is
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an excellent choice.  It is also helpful that the starter messages that are
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// placed in the queue when new task arrive also awakens DoRunLoop.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT MessagePumpForUI : public MessagePumpWin {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The application-defined code passed to the hook procedure.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kMessageFilterCode = 0x5001;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessagePumpForUI();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MessagePumpForUI();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MessagePump methods:
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ScheduleWork();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static LRESULT CALLBACK WndProcThunk(HWND window_handle,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       UINT message,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       WPARAM wparam,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       LPARAM lparam);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DoRunLoop();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitMessageWnd();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForWork();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleWorkMessage();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleTimerMessage();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ProcessNextWindowsMessage();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ProcessMessageHelper(const MSG& msg);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ProcessPumpReplacementMessage();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  // Atom representing the registered window class.
1395e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  ATOM atom_;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A hidden message-only window.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HWND message_hwnd_;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessagePumpForIO extends MessagePumpWin with methods that are particular to a
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessageLoop instantiated with TYPE_IO. This version of MessagePump does not
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deal with Windows mesagges, and instead has a Run loop based on Completion
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ports so it is better suited for IO operations.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT MessagePumpForIO : public MessagePumpWin {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct IOContext;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clients interested in receiving OS notifications when asynchronous IO
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // operations complete should implement this interface and register themselves
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with the message pump.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Typical use #1:
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   // Use only when there are no user's buffers involved on the actual IO,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   // so that all the cleanup can be done by the message pump.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   class MyFile : public IOHandler {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     MyFile() {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       ...
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       context_ = new IOContext;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       context_->handler = this;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       message_pump->RegisterIOHandler(file_, this);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     ~MyFile() {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       if (pending_) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //         // By setting the handler to NULL, we're asking for this context
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //         // to be deleted when received, without calling back to us.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //         context_->handler = NULL;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       } else {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //         delete context_;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                                DWORD error) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //         pending_ = false;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     void DoSomeIo() {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       ...
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       // The only buffer required for this operation is the overlapped
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       // structure.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       ConnectNamedPipe(file_, &context_->overlapped);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       pending_ = true;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     bool pending_;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     IOContext* context_;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     HANDLE file_;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   };
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Typical use #2:
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   class MyFile : public IOHandler {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     MyFile() {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       ...
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       message_pump->RegisterIOHandler(file_, this);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     // Plus some code to make sure that this destructor is not called
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     // while there are pending IO operations.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     ~MyFile() {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                                DWORD error) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       ...
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       delete context;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     void DoSomeIo() {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       ...
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       IOContext* context = new IOContext;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       // This is not used for anything. It just prevents the context from
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       // being considered "abandoned".
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       context->handler = this;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       ReadFile(file_, buffer, num_bytes, &read, &context->overlapped);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     HANDLE file_;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   };
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Typical use #3:
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Same as the previous example, except that in order to deal with the
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // requirement stated for the destructor, the class calls WaitForIOCompletion
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from the destructor to block until all IO finishes.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     ~MyFile() {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //       while(pending_)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //         message_pump->WaitForIOCompletion(INFINITE, this);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class IOHandler {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~IOHandler() {}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will be called once the pending IO operation associated with
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |context| completes. |error| is the Win32 error code of the IO operation
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (ERROR_SUCCESS if there was no error). |bytes_transfered| will be zero
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // on error.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               DWORD error) = 0;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An IOObserver is an object that receives IO notifications from the
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MessagePump.
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: An IOObserver implementation should be extremely fast!
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class IOObserver {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IOObserver() {}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void WillProcessIOEvent() = 0;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void DidProcessIOEvent() = 0;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   protected:
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~IOObserver() {}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The extended context that should be used as the base structure on every
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // overlapped IO operation. |handler| must be set to the registered IOHandler
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for the given file when the operation is started, and it can be set to NULL
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // before the operation completes to indicate that the handler should not be
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // called anymore, and instead, the IOContext should be deleted when the OS
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notifies the completion of this operation. Please remember that any buffers
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // involved with an IO operation should be around until the callback is
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // received, so this technique can only be used for IO that do not involve
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // additional buffers (other than the overlapped structure itself).
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct IOContext {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OVERLAPPED overlapped;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IOHandler* handler;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessagePumpForIO();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MessagePumpForIO() {}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MessagePump methods:
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ScheduleWork();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register the handler to be used when asynchronous IO for the given file
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // completes. The registration persists as long as |file_handle| is valid, so
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |handler| must be valid as long as there is pending IO for the given file.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RegisterIOHandler(HANDLE file_handle, IOHandler* handler);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register the handler to be used to process job events. The registration
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // persists as long as the job object is live, so |handler| must be valid
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // until the job object is destroyed. Returns true if the registration
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // succeeded, and false otherwise.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool RegisterJobObject(HANDLE job_handle, IOHandler* handler);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Waits for the next IO completion that should be processed by |filter|, for
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // up to |timeout| milliseconds. Return true if any IO operation completed,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // regardless of the involved handler, and false if the timeout expired. If
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the completion port received any message and the involved IO handler
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // matches |filter|, the callback is called before returning from this code;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if the handler is not the one that we are looking for, the callback will
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be postponed for another time, so reentrancy problems can be avoided.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // External use of this method should be reserved for the rare case when the
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // caller is willing to allow pausing regular task dispatching on this thread.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool WaitForIOCompletion(DWORD timeout, IOHandler* filter);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddIOObserver(IOObserver* obs);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RemoveIOObserver(IOObserver* obs);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct IOItem {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IOHandler* handler;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IOContext* context;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD bytes_transfered;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD error;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In some cases |context| can be a non-pointer value casted to a pointer.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |has_valid_io_context| is true if |context| is a valid IOContext
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // pointer, and false otherwise.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool has_valid_io_context;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DoRunLoop();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForWork();
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool MatchCompletedIOItem(IOHandler* filter, IOItem* item);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetIOItem(DWORD timeout, IOItem* item);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ProcessInternalIOItem(const IOItem& item);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WillProcessIOEvent();
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DidProcessIOEvent();
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Converts an IOHandler pointer to a completion port key.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |has_valid_io_context| specifies whether completion packets posted to
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |handler| will have valid OVERLAPPED pointers.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ULONG_PTR HandlerToKey(IOHandler* handler, bool has_valid_io_context);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Converts a completion port key to an IOHandler pointer.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static IOHandler* KeyToHandler(ULONG_PTR key, bool* has_valid_io_context);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The completion port associated with this thread.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  win::ScopedHandle port_;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This list will be empty almost always. It stores IO completions that have
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not been delivered yet because somebody was doing cleanup.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::list<IOItem> completed_io_;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObserverList<IOObserver> io_observers_;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_
342