message_pump.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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_H_
  5. #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_
  6. #include <memory>
  7. #include <utility>
  8. #include "base/base_export.h"
  9. #include "base/check.h"
  10. #include "base/check_op.h"
  11. #include "base/memory/raw_ptr_exclusion.h"
  12. #include "base/message_loop/message_pump_type.h"
  13. #include "base/message_loop/timer_slack.h"
  14. #include "base/sequence_checker.h"
  15. #include "base/time/time.h"
  16. #include "build/build_config.h"
  17. namespace base {
  18. class TimeTicks;
  19. class BASE_EXPORT MessagePump {
  20. public:
  21. using MessagePumpFactory = std::unique_ptr<MessagePump>();
  22. // Uses the given base::MessagePumpFactory to override the default MessagePump
  23. // implementation for 'MessagePumpType::UI'. May only be called once.
  24. static void OverrideMessagePumpForUIFactory(MessagePumpFactory* factory);
  25. // Returns true if the MessagePumpForUI has been overidden.
  26. static bool IsMessagePumpForUIFactoryOveridden();
  27. // Creates the default MessagePump based on |type|. Caller owns return value.
  28. static std::unique_ptr<MessagePump> Create(MessagePumpType type);
  29. // Please see the comments above the Run method for an illustration of how
  30. // these delegate methods are used.
  31. class BASE_EXPORT Delegate {
  32. public:
  33. virtual ~Delegate() = default;
  34. struct NextWorkInfo {
  35. // Helper to extract a TimeDelta for pumps that need a
  36. // timeout-till-next-task.
  37. TimeDelta remaining_delay() const {
  38. DCHECK(!delayed_run_time.is_null() && !delayed_run_time.is_max());
  39. DCHECK_GE(TimeTicks::Now(), recent_now);
  40. return delayed_run_time - recent_now;
  41. }
  42. // Helper to verify if the next task is ready right away.
  43. bool is_immediate() const { return delayed_run_time.is_null(); }
  44. // The next PendingTask's |delayed_run_time|. is_null() if there's extra
  45. // work to run immediately. is_max() if there are no more immediate nor
  46. // delayed tasks.
  47. TimeTicks delayed_run_time;
  48. // A recent view of TimeTicks::Now(). Only valid if |delayed_run_time|
  49. // isn't null nor max. MessagePump impls should use remaining_delay()
  50. // instead of resampling Now() if they wish to sleep for a TimeDelta.
  51. TimeTicks recent_now;
  52. // If true, native messages should be processed before executing more work
  53. // from the Delegate. This is an optional hint; not all message pumpls
  54. // implement this.
  55. bool yield_to_native = false;
  56. };
  57. // Executes an immediate task or a ripe delayed task. Returns information
  58. // about when DoWork() should be called again. If the returned NextWorkInfo
  59. // is_immediate(), DoWork() must be invoked again shortly. Else, DoWork()
  60. // must be invoked at |NextWorkInfo::delayed_run_time| or when
  61. // ScheduleWork() is invoked, whichever comes first. Redundant/spurious
  62. // invocations of DoWork() outside of those requirements are tolerated.
  63. // DoIdleWork() will not be called so long as this returns a NextWorkInfo
  64. // which is_immediate().
  65. virtual NextWorkInfo DoWork() = 0;
  66. // Called from within Run just before the message pump goes to sleep.
  67. // Returns true to indicate that idle work was done. Returning false means
  68. // the pump will now wait.
  69. virtual bool DoIdleWork() = 0;
  70. class ScopedDoWorkItem {
  71. public:
  72. ScopedDoWorkItem() : outer_(nullptr) {}
  73. ~ScopedDoWorkItem() {
  74. if (outer_)
  75. outer_->OnEndWorkItem();
  76. }
  77. ScopedDoWorkItem(ScopedDoWorkItem&& rhs)
  78. : outer_(std::exchange(rhs.outer_, nullptr)) {}
  79. ScopedDoWorkItem& operator=(ScopedDoWorkItem&& rhs) {
  80. outer_ = std::exchange(rhs.outer_, nullptr);
  81. return *this;
  82. }
  83. private:
  84. friend Delegate;
  85. explicit ScopedDoWorkItem(Delegate* outer) : outer_(outer) {
  86. outer_->OnBeginWorkItem();
  87. }
  88. // `outer_` is not a raw_ptr<...> for performance reasons (based on
  89. // analysis of sampling profiler data and tab_search:top100:2020).
  90. RAW_PTR_EXCLUSION Delegate* outer_;
  91. };
  92. // Called before a unit of work is executed. This allows reports
  93. // about individual units of work to be produced. The unit of work ends when
  94. // the returned ScopedDoWorkItem goes out of scope.
  95. // TODO(crbug.com/851163): Place calls for all platforms. Without this, some
  96. // state like the top-level "ThreadController active" trace event will not
  97. // be correct when work is performed.
  98. [[nodiscard]] ScopedDoWorkItem BeginWorkItem() {
  99. return ScopedDoWorkItem(this);
  100. }
  101. // Called before the message pump starts waiting for work. This indicates
  102. // that the message pump is idle (out of application work and ideally out of
  103. // native work -- if it can tell).
  104. virtual void BeforeWait() = 0;
  105. private:
  106. // Called upon entering/exiting a ScopedDoWorkItem.
  107. virtual void OnBeginWorkItem() = 0;
  108. virtual void OnEndWorkItem() = 0;
  109. };
  110. MessagePump();
  111. virtual ~MessagePump();
  112. // The Run method is called to enter the message pump's run loop.
  113. //
  114. // Within the method, the message pump is responsible for processing native
  115. // messages as well as for giving cycles to the delegate periodically. The
  116. // message pump should take care to mix delegate callbacks with native message
  117. // processing so neither type of event starves the other of cycles. Each call
  118. // to a delegate function is considered the beginning of a new "unit of work".
  119. //
  120. // The anatomy of a typical run loop:
  121. //
  122. // for (;;) {
  123. // bool did_native_work = false;
  124. // {
  125. // auto scoped_do_work_item = state_->delegate->BeginWorkItem();
  126. // did_native_work = DoNativeWork();
  127. // }
  128. // if (should_quit_)
  129. // break;
  130. //
  131. // Delegate::NextWorkInfo next_work_info = delegate->DoWork();
  132. // if (should_quit_)
  133. // break;
  134. //
  135. // if (did_native_work || next_work_info.is_immediate())
  136. // continue;
  137. //
  138. // bool did_idle_work = delegate_->DoIdleWork();
  139. // if (should_quit_)
  140. // break;
  141. //
  142. // if (did_idle_work)
  143. // continue;
  144. //
  145. // WaitForWork();
  146. // }
  147. //
  148. // Here, DoNativeWork is some private method of the message pump that is
  149. // responsible for dispatching the next UI message or notifying the next IO
  150. // completion (for example). WaitForWork is a private method that simply
  151. // blocks until there is more work of any type to do.
  152. //
  153. // Notice that the run loop cycles between calling DoNativeWork and DoWork
  154. // methods. This helps ensure that none of these work queues starve the
  155. // others. This is important for message pumps that are used to drive
  156. // animations, for example.
  157. //
  158. // Notice also that after each callout to foreign code, the run loop checks to
  159. // see if it should quit. The Quit method is responsible for setting this
  160. // flag. No further work is done once the quit flag is set.
  161. //
  162. // NOTE 1: Run may be called reentrantly from any of the callouts to foreign
  163. // code (internal work, DoWork, DoIdleWork). As a result, DoWork and
  164. // DoIdleWork must be reentrant.
  165. //
  166. // NOTE 2: Run implementations must arrange for DoWork to be invoked as
  167. // expected if a callout to foreign code enters a message pump outside their
  168. // control. For example, the MessageBox API on Windows pumps UI messages. If
  169. // the MessageBox API is called (indirectly) from within Run, it is expected
  170. // that DoWork will be invoked from within that call in response to
  171. // ScheduleWork or as requested by the last NextWorkInfo returned by DoWork.
  172. // The MessagePump::Delegate may then elect to do nested work or not depending
  173. // on its policy in that context. Regardless of that decision (and return
  174. // value of the nested DoWork() call), DoWork() will be invoked again when the
  175. // nested loop unwinds.
  176. virtual void Run(Delegate* delegate) = 0;
  177. // Quit immediately from the most recently entered run loop. This method may
  178. // only be used on the thread that called Run.
  179. virtual void Quit() = 0;
  180. // Schedule a DoWork callback to happen reasonably soon. Does nothing if a
  181. // DoWork callback is already scheduled. Once this call is made, DoWork is
  182. // guaranteed to be called repeatedly at least until it returns a
  183. // non-immediate NextWorkInfo. This call can be expensive and callers should
  184. // attempt not to invoke it again before a non-immediate NextWorkInfo was
  185. // returned from DoWork(). Thread-safe (and callers should avoid holding a
  186. // Lock at all cost while making this call as some platforms' priority
  187. // boosting features have been observed to cause the caller to get descheduled
  188. // : https://crbug.com/890978).
  189. virtual void ScheduleWork() = 0;
  190. // Schedule a DoWork callback to happen at the specified time, cancelling any
  191. // pending callback scheduled by this method. This method may only be used on
  192. // the thread that called Run.
  193. //
  194. // It isn't necessary to call this during normal execution, as the pump wakes
  195. // up as requested by the return value of DoWork().
  196. // TODO(crbug.com/885371): Determine if this must be called to ensure that
  197. // delayed tasks run when a message pump outside the control of Run is
  198. // entered.
  199. virtual void ScheduleDelayedWork(
  200. const Delegate::NextWorkInfo& next_work_info) = 0;
  201. // Sets the timer slack to the specified value.
  202. virtual void SetTimerSlack(TimerSlack timer_slack);
  203. };
  204. } // namespace base
  205. #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_