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