message_pump_win.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_
  5. #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_
  6. #include <windows.h>
  7. #include <atomic>
  8. #include <list>
  9. #include <memory>
  10. #include "base/base_export.h"
  11. #include "base/location.h"
  12. #include "base/message_loop/message_pump.h"
  13. #include "base/observer_list.h"
  14. #include "base/optional.h"
  15. #include "base/threading/thread_checker.h"
  16. #include "base/time/time.h"
  17. #include "base/win/message_window.h"
  18. #include "base/win/scoped_handle.h"
  19. namespace base {
  20. // MessagePumpWin serves as the base for specialized versions of the MessagePump
  21. // for Windows. It provides basic functionality like handling of observers and
  22. // controlling the lifetime of the message pump.
  23. class BASE_EXPORT MessagePumpWin : public MessagePump {
  24. public:
  25. MessagePumpWin();
  26. ~MessagePumpWin() override;
  27. // MessagePump methods:
  28. void Run(Delegate* delegate) override;
  29. void Quit() override;
  30. protected:
  31. struct RunState {
  32. Delegate* delegate;
  33. // Used to flag that the current Run() invocation should return ASAP.
  34. bool should_quit;
  35. // Used to count how many Run() invocations are on the stack.
  36. int run_depth;
  37. };
  38. virtual void DoRunLoop() = 0;
  39. // True iff:
  40. // * MessagePumpForUI: there's a kMsgDoWork message pending in the Windows
  41. // Message queue. i.e. when:
  42. // a. The pump is about to wakeup from idle.
  43. // b. The pump is about to enter a nested native loop and a
  44. // ScopedNestableTaskAllower was instantiated to allow application
  45. // tasks to execute in that nested loop (ScopedNestableTaskAllower
  46. // invokes ScheduleWork()).
  47. // c. While in a native (nested) loop : HandleWorkMessage() =>
  48. // ProcessPumpReplacementMessage() invokes ScheduleWork() before
  49. // processing a native message to guarantee this pump will get another
  50. // time slice if it goes into native Windows code and enters a native
  51. // nested loop. This is different from (b.) because we're not yet
  52. // processing an application task at the current run level and
  53. // therefore are expected to keep pumping application tasks without
  54. // necessitating a ScopedNestableTaskAllower.
  55. //
  56. // * MessagePumpforIO: there's a dummy IO completion item with |this| as an
  57. // lpCompletionKey in the queue which is about to wakeup
  58. // WaitForIOCompletion(). MessagePumpForIO doesn't support nesting so
  59. // this is simpler than MessagePumpForUI.
  60. std::atomic_bool work_scheduled_{false};
  61. // State for the current invocation of Run.
  62. RunState* state_ = nullptr;
  63. THREAD_CHECKER(bound_thread_);
  64. };
  65. //-----------------------------------------------------------------------------
  66. // MessagePumpForUI extends MessagePumpWin with methods that are particular to a
  67. // MessageLoop instantiated with TYPE_UI.
  68. //
  69. // MessagePumpForUI implements a "traditional" Windows message pump. It contains
  70. // a nearly infinite loop that peeks out messages, and then dispatches them.
  71. // Intermixed with those peeks are callouts to DoWork. When there are no
  72. // events to be serviced, this pump goes into a wait state. In most cases, this
  73. // message pump handles all processing.
  74. //
  75. // However, when a task, or windows event, invokes on the stack a native dialog
  76. // box or such, that window typically provides a bare bones (native?) message
  77. // pump. That bare-bones message pump generally supports little more than a
  78. // peek of the Windows message queue, followed by a dispatch of the peeked
  79. // message. MessageLoop extends that bare-bones message pump to also service
  80. // Tasks, at the cost of some complexity.
  81. //
  82. // The basic structure of the extension (referred to as a sub-pump) is that a
  83. // special message, kMsgHaveWork, is repeatedly injected into the Windows
  84. // Message queue. Each time the kMsgHaveWork message is peeked, checks are made
  85. // for an extended set of events, including the availability of Tasks to run.
  86. //
  87. // After running a task, the special message kMsgHaveWork is again posted to the
  88. // Windows Message queue, ensuring a future time slice for processing a future
  89. // event. To prevent flooding the Windows Message queue, care is taken to be
  90. // sure that at most one kMsgHaveWork message is EVER pending in the Window's
  91. // Message queue.
  92. //
  93. // There are a few additional complexities in this system where, when there are
  94. // no Tasks to run, this otherwise infinite stream of messages which drives the
  95. // sub-pump is halted. The pump is automatically re-started when Tasks are
  96. // queued.
  97. //
  98. // A second complexity is that the presence of this stream of posted tasks may
  99. // prevent a bare-bones message pump from ever peeking a WM_PAINT or WM_TIMER.
  100. // Such paint and timer events always give priority to a posted message, such as
  101. // kMsgHaveWork messages. As a result, care is taken to do some peeking in
  102. // between the posting of each kMsgHaveWork message (i.e., after kMsgHaveWork is
  103. // peeked, and before a replacement kMsgHaveWork is posted).
  104. //
  105. // NOTE: Although it may seem odd that messages are used to start and stop this
  106. // flow (as opposed to signaling objects, etc.), it should be understood that
  107. // the native message pump will *only* respond to messages. As a result, it is
  108. // an excellent choice. It is also helpful that the starter messages that are
  109. // placed in the queue when new task arrive also awakens DoRunLoop.
  110. //
  111. class BASE_EXPORT MessagePumpForUI : public MessagePumpWin {
  112. public:
  113. MessagePumpForUI();
  114. ~MessagePumpForUI() override;
  115. // MessagePump methods:
  116. void ScheduleWork() override;
  117. void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
  118. // Make the MessagePumpForUI respond to WM_QUIT messages.
  119. void EnableWmQuit();
  120. // An observer interface to give the scheduler an opportunity to log
  121. // information about MSGs before and after they are dispatched.
  122. class BASE_EXPORT Observer {
  123. public:
  124. virtual void WillDispatchMSG(const MSG& msg) = 0;
  125. virtual void DidDispatchMSG(const MSG& msg) = 0;
  126. };
  127. void AddObserver(Observer* observer);
  128. void RemoveObserver(Observer* obseerver);
  129. private:
  130. bool MessageCallback(UINT message,
  131. WPARAM wparam,
  132. LPARAM lparam,
  133. LRESULT* result);
  134. void DoRunLoop() override;
  135. void WaitForWork(Delegate::NextWorkInfo next_work_info);
  136. void HandleWorkMessage();
  137. void HandleTimerMessage();
  138. void ScheduleNativeTimer(Delegate::NextWorkInfo next_work_info);
  139. void KillNativeTimer();
  140. bool ProcessNextWindowsMessage();
  141. bool ProcessMessageHelper(const MSG& msg);
  142. bool ProcessPumpReplacementMessage();
  143. base::win::MessageWindow message_window_;
  144. // Whether MessagePumpForUI responds to WM_QUIT messages or not.
  145. // TODO(thestig): Remove when the Cloud Print Service goes away.
  146. bool enable_wm_quit_ = false;
  147. // Non-nullopt if there's currently a native timer installed. If so, it
  148. // indicates when the timer is set to fire and can be used to avoid setting
  149. // redundant timers.
  150. Optional<TimeTicks> installed_native_timer_;
  151. // This will become true when a native loop takes our kMsgHaveWork out of the
  152. // system queue. It will be reset to false whenever DoRunLoop regains control.
  153. // Used to decide whether ScheduleDelayedWork() should start a native timer.
  154. bool in_native_loop_ = false;
  155. ObserverList<Observer>::Unchecked observers_;
  156. };
  157. //-----------------------------------------------------------------------------
  158. // MessagePumpForIO extends MessagePumpWin with methods that are particular to a
  159. // MessageLoop instantiated with TYPE_IO. This version of MessagePump does not
  160. // deal with Windows mesagges, and instead has a Run loop based on Completion
  161. // Ports so it is better suited for IO operations.
  162. //
  163. class BASE_EXPORT MessagePumpForIO : public MessagePumpWin {
  164. public:
  165. struct BASE_EXPORT IOContext {
  166. IOContext();
  167. OVERLAPPED overlapped;
  168. };
  169. // Clients interested in receiving OS notifications when asynchronous IO
  170. // operations complete should implement this interface and register themselves
  171. // with the message pump.
  172. //
  173. // Typical use #1:
  174. // class MyFile : public IOHandler {
  175. // MyFile() : IOHandler(FROM_HERE) {
  176. // ...
  177. // message_pump->RegisterIOHandler(file_, this);
  178. // }
  179. // // Plus some code to make sure that this destructor is not called
  180. // // while there are pending IO operations.
  181. // ~MyFile() {
  182. // }
  183. // virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered,
  184. // DWORD error) {
  185. // ...
  186. // delete context;
  187. // }
  188. // void DoSomeIo() {
  189. // ...
  190. // IOContext* context = new IOContext;
  191. // ReadFile(file_, buffer, num_bytes, &read, &context);
  192. // }
  193. // HANDLE file_;
  194. // };
  195. //
  196. // Typical use #2:
  197. // Same as the previous example, except that in order to deal with the
  198. // requirement stated for the destructor, the class calls WaitForIOCompletion
  199. // from the destructor to block until all IO finishes.
  200. // ~MyFile() {
  201. // while(pending_)
  202. // message_pump->WaitForIOCompletion(INFINITE, this);
  203. // }
  204. //
  205. class BASE_EXPORT IOHandler {
  206. public:
  207. explicit IOHandler(const Location& from_here);
  208. virtual ~IOHandler();
  209. IOHandler(const IOHandler&) = delete;
  210. IOHandler& operator=(const IOHandler&) = delete;
  211. // This will be called once the pending IO operation associated with
  212. // |context| completes. |error| is the Win32 error code of the IO operation
  213. // (ERROR_SUCCESS if there was no error). |bytes_transfered| will be zero
  214. // on error.
  215. virtual void OnIOCompleted(IOContext* context,
  216. DWORD bytes_transfered,
  217. DWORD error) = 0;
  218. const Location& io_handler_location() { return io_handler_location_; }
  219. private:
  220. const Location io_handler_location_;
  221. };
  222. MessagePumpForIO();
  223. ~MessagePumpForIO() override;
  224. // MessagePump methods:
  225. void ScheduleWork() override;
  226. void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
  227. // Register the handler to be used when asynchronous IO for the given file
  228. // completes. The registration persists as long as |file_handle| is valid, so
  229. // |handler| must be valid as long as there is pending IO for the given file.
  230. HRESULT RegisterIOHandler(HANDLE file_handle, IOHandler* handler);
  231. // Register the handler to be used to process job events. The registration
  232. // persists as long as the job object is live, so |handler| must be valid
  233. // until the job object is destroyed. Returns true if the registration
  234. // succeeded, and false otherwise.
  235. bool RegisterJobObject(HANDLE job_handle, IOHandler* handler);
  236. // Waits for the next IO completion that should be processed by |filter|, for
  237. // up to |timeout| milliseconds. Return true if any IO operation completed,
  238. // regardless of the involved handler, and false if the timeout expired. If
  239. // the completion port received any message and the involved IO handler
  240. // matches |filter|, the callback is called before returning from this code;
  241. // if the handler is not the one that we are looking for, the callback will
  242. // be postponed for another time, so reentrancy problems can be avoided.
  243. // External use of this method should be reserved for the rare case when the
  244. // caller is willing to allow pausing regular task dispatching on this thread.
  245. bool WaitForIOCompletion(DWORD timeout, IOHandler* filter);
  246. private:
  247. struct IOItem {
  248. IOHandler* handler;
  249. IOContext* context;
  250. DWORD bytes_transfered;
  251. DWORD error;
  252. };
  253. void DoRunLoop() override;
  254. void WaitForWork(Delegate::NextWorkInfo next_work_info);
  255. bool MatchCompletedIOItem(IOHandler* filter, IOItem* item);
  256. bool GetIOItem(DWORD timeout, IOItem* item);
  257. bool ProcessInternalIOItem(const IOItem& item);
  258. // The completion port associated with this thread.
  259. win::ScopedHandle port_;
  260. // This list will be empty almost always. It stores IO completions that have
  261. // not been delivered yet because somebody was doing cleanup.
  262. std::list<IOItem> completed_io_;
  263. };
  264. } // namespace base
  265. #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_