blob: 3151a5cbfa589b726ccabac091bc8e27e6eca03b [file] [log] [blame]
[email protected]f2ebbf062012-04-06 03:14:301// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
[email protected]295039bd2008-08-15 04:32:574
[email protected]59e69e742013-06-18 20:27:525#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_
6#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_
[email protected]295039bd2008-08-15 04:32:577
[email protected]0bea7252011-08-05 15:34:008#include "base/base_export.h"
Hans Wennborg7b533712020-06-22 20:52:279#include "base/check_op.h"
Carlos Caballerod70e6032019-07-30 12:27:2710#include "base/message_loop/message_pump_type.h"
[email protected]57cd3d22014-06-05 19:36:2011#include "base/message_loop/timer_slack.h"
gab7d2fae42017-06-01 14:02:5512#include "base/sequence_checker.h"
Gabriel Charette06c34972019-02-04 18:38:3513#include "base/time/time.h"
Alex Clarke636e7052019-05-30 10:49:3714#include "build/build_config.h"
[email protected]295039bd2008-08-15 04:32:5715
[email protected]295039bd2008-08-15 04:32:5716namespace base {
17
[email protected]7e7fab42010-11-06 22:23:2918class TimeTicks;
[email protected]e1acf6f2008-10-27 20:43:3319
gab7d2fae42017-06-01 14:02:5520class BASE_EXPORT MessagePump {
[email protected]295039bd2008-08-15 04:32:5721 public:
Alex Clarke636e7052019-05-30 10:49:3722 using MessagePumpFactory = std::unique_ptr<MessagePump>();
23 // Uses the given base::MessagePumpFactory to override the default MessagePump
Carlos Caballerob2e5b6d82019-09-04 09:04:3924 // implementation for 'MessagePumpType::UI'. May only be called once.
Alex Clarke636e7052019-05-30 10:49:3725 static void OverrideMessagePumpForUIFactory(MessagePumpFactory* factory);
26
27 // Returns true if the MessagePumpForUI has been overidden.
28 static bool IsMessagePumpForUIFactoryOveridden();
29
30 // Creates the default MessagePump based on |type|. Caller owns return value.
Carlos Caballerod70e6032019-07-30 12:27:2731 static std::unique_ptr<MessagePump> Create(MessagePumpType type);
Alex Clarke636e7052019-05-30 10:49:3732
[email protected]295039bd2008-08-15 04:32:5733 // Please see the comments above the Run method for an illustration of how
34 // these delegate methods are used.
[email protected]0bea7252011-08-05 15:34:0035 class BASE_EXPORT Delegate {
[email protected]295039bd2008-08-15 04:32:5736 public:
Chris Watkins091d6292017-12-13 04:25:5837 virtual ~Delegate() = default;
[email protected]b16ef312008-08-19 18:36:2338
Olivier Li26dede52020-02-27 19:33:5939 // Called before a unit of work internal to the message pump is executed.
Etienne Pierre-doray2163f3012020-04-02 21:37:1440 // This allows reports about individual units of work to be produced. The
41 // unit of work ends when BeforeDoInternalWork() is called again, or when
42 // BeforeWait(), DoWork(), or DoIdleWork() is called.
Olivier Li26dede52020-02-27 19:33:5943 // TODO(crbug.com/851163): Place calls for all platforms.
Mike Wittman45a9b6b2019-02-06 18:06:2144 virtual void BeforeDoInternalWork() = 0;
Mike Wittmancb1067c2019-01-24 19:04:0045
Olivier Li26dede52020-02-27 19:33:5946 // Called before the message pump starts waiting for work.
47 // This indicates the end of the current unit of work, which is required
48 // to produce reports about individual units of work.
49 virtual void BeforeWait() = 0;
50
Gabriel Charette06c34972019-02-04 18:38:3551 struct NextWorkInfo {
52 // Helper to extract a TimeDelta for pumps that need a
53 // timeout-till-next-task.
54 TimeDelta remaining_delay() const {
55 DCHECK(!delayed_run_time.is_null() && !delayed_run_time.is_max());
56 DCHECK_GE(TimeTicks::Now(), recent_now);
57 return delayed_run_time - recent_now;
58 }
59
60 // Helper to verify if the next task is ready right away.
61 bool is_immediate() const { return delayed_run_time.is_null(); }
62
63 // The next PendingTask's |delayed_run_time|. is_null() if there's extra
64 // work to run immediately. is_max() if there are no more immediate nor
65 // delayed tasks.
66 TimeTicks delayed_run_time;
67
68 // A recent view of TimeTicks::Now(). Only valid if |next_task_run_time|
69 // isn't null nor max. MessagePump impls should use remaining_delay()
70 // instead of resampling Now() if they wish to sleep for a TimeDelta.
71 TimeTicks recent_now;
72 };
73
Francois Dorayb61fcc112020-03-25 21:11:5874 // Executes an immediate task or a ripe delayed task. Returns information
Etienne Pierre-doray2163f3012020-04-02 21:37:1475 // about when DoWork() should be called again. If the returned NextWorkInfo
76 // is_immediate(), DoWork() must be invoked again shortly. Else, DoWork()
77 // must be invoked at |NextWorkInfo::delayed_run_time| or when
78 // ScheduleWork() is invoked, whichever comes first. Redundant/spurious
79 // invocations of DoWork() outside of those requirements are tolerated.
Francois Dorayb61fcc112020-03-25 21:11:5880 // DoIdleWork() will not be called so long as this returns a NextWorkInfo
81 // which is_immediate().
Etienne Pierre-doray2163f3012020-04-02 21:37:1482 virtual NextWorkInfo DoWork() = 0;
Gabriel Charette06c34972019-02-04 18:38:3583
[email protected]295039bd2008-08-15 04:32:5784 // Called from within Run just before the message pump goes to sleep.
cpuee8907952014-08-28 23:25:3785 // Returns true to indicate that idle work was done. Returning false means
86 // the pump will now wait.
[email protected]295039bd2008-08-15 04:32:5787 virtual bool DoIdleWork() = 0;
88 };
89
[email protected]d4799a32010-09-28 22:54:5890 MessagePump();
[email protected]54aa4f12013-07-22 22:24:1391 virtual ~MessagePump();
[email protected]52a261f2009-03-03 15:01:1292
[email protected]295039bd2008-08-15 04:32:5793 // The Run method is called to enter the message pump's run loop.
94 //
95 // Within the method, the message pump is responsible for processing native
Olivier Li26dede52020-02-27 19:33:5996 // messages as well as for giving cycles to the delegate periodically. The
Francois Dorayb61fcc112020-03-25 21:11:5897 // message pump should take care to mix delegate callbacks with native message
98 // processing so neither type of event starves the other of cycles. Each call
99 // to a delegate function or DoInternalWork() is considered the beginning of a
100 // new "unit of work".
[email protected]295039bd2008-08-15 04:32:57101 //
102 // The anatomy of a typical run loop:
103 //
104 // for (;;) {
Francois Dorayb61fcc112020-03-25 21:11:58105 // bool did_internal_work = DoInternalWork();
[email protected]295039bd2008-08-15 04:32:57106 // if (should_quit_)
107 // break;
[email protected]9bcbf472008-08-30 00:22:48108 //
Etienne Pierre-doray2163f3012020-04-02 21:37:14109 // Delegate::NextWorkInfo next_work_info = delegate->DoWork();
[email protected]295039bd2008-08-15 04:32:57110 // if (should_quit_)
111 // break;
[email protected]295039bd2008-08-15 04:32:57112 //
Francois Dorayb61fcc112020-03-25 21:11:58113 // if (did_internal_work || next_work_info.is_immediate())
[email protected]295039bd2008-08-15 04:32:57114 // continue;
115 //
Francois Dorayb61fcc112020-03-25 21:11:58116 // bool did_idle_work = delegate_->DoIdleWork();
[email protected]295039bd2008-08-15 04:32:57117 // if (should_quit_)
118 // break;
[email protected]9bcbf472008-08-30 00:22:48119 //
Francois Dorayb61fcc112020-03-25 21:11:58120 // if (did_idle_work)
[email protected]295039bd2008-08-15 04:32:57121 // continue;
122 //
123 // WaitForWork();
124 // }
125 //
Francois Dorayb61fcc112020-03-25 21:11:58126
[email protected]295039bd2008-08-15 04:32:57127 // Here, DoInternalWork is some private method of the message pump that is
128 // responsible for dispatching the next UI message or notifying the next IO
129 // completion (for example). WaitForWork is a private method that simply
130 // blocks until there is more work of any type to do.
131 //
Etienne Pierre-doray2163f3012020-04-02 21:37:14132 // Notice that the run loop cycles between calling DoInternalWork and DoWork
133 // methods. This helps ensure that none of these work queues starve the
134 // others. This is important for message pumps that are used to drive
Francois Dorayb61fcc112020-03-25 21:11:58135 // animations, for example.
[email protected]295039bd2008-08-15 04:32:57136 //
Francois Dorayb61fcc112020-03-25 21:11:58137 // Notice also that after each callout to foreign code, the run loop checks to
138 // see if it should quit. The Quit method is responsible for setting this
[email protected]295039bd2008-08-15 04:32:57139 // flag. No further work is done once the quit flag is set.
140 //
Francois Dorayb61fcc112020-03-25 21:11:58141 // NOTE 1: Run may be called reentrantly from any of the callouts to foreign
Etienne Pierre-doray2163f3012020-04-02 21:37:14142 // code (internal work, DoWork, DoIdleWork). As a result, DoWork and
Francois Dorayb61fcc112020-03-25 21:11:58143 // DoIdleWork must be reentrant.
[email protected]52a261f2009-03-03 15:01:12144 //
Etienne Pierre-doray2163f3012020-04-02 21:37:14145 // NOTE 2: Run implementations must arrange for DoWork to be invoked as
Francois Dorayb61fcc112020-03-25 21:11:58146 // expected if a callout to foreign code enters a message pump outside their
147 // control. For example, the MessageBox API on Windows pumps UI messages. If
148 // the MessageBox API is called (indirectly) from within Run, it is expected
Etienne Pierre-doray2163f3012020-04-02 21:37:14149 // that DoWork will be invoked from within that call in response to
150 // ScheduleWork or as requested by the last NextWorkInfo returned by DoWork.
151 // The MessagePump::Delegate may then elect to do nested work or not depending
152 // on its policy in that context. Regardless of that decision (and return
153 // value of the nested DoWork() call), DoWork() will be invoked again when the
154 // nested loop unwinds.
[email protected]295039bd2008-08-15 04:32:57155 virtual void Run(Delegate* delegate) = 0;
156
157 // Quit immediately from the most recently entered run loop. This method may
158 // only be used on the thread that called Run.
159 virtual void Quit() = 0;
160
Etienne Pierre-doray2163f3012020-04-02 21:37:14161 // Schedule a DoWork callback to happen reasonably soon. Does nothing if a
162 // DoWork callback is already scheduled. Once this call is made, DoWork is
163 // guaranteed to be called repeatedly at least until it returns a
164 // non-immediate NextWorkInfo. This call can be expensive and callers should
Francois Dorayb61fcc112020-03-25 21:11:58165 // attempt not to invoke it again before a non-immediate NextWorkInfo was
Etienne Pierre-doray2163f3012020-04-02 21:37:14166 // returned from DoWork(). Thread-safe (and callers should avoid holding a
Francois Dorayb61fcc112020-03-25 21:11:58167 // Lock at all cost while making this call as some platforms' priority
168 // boosting features have been observed to cause the caller to get descheduled
169 // : https://crbug.com/890978).
[email protected]295039bd2008-08-15 04:32:57170 virtual void ScheduleWork() = 0;
171
Etienne Pierre-doray2163f3012020-04-02 21:37:14172 // Schedule a DoWork callback to happen at the specified time, cancelling any
173 // pending callback scheduled by this method. This method may only be used on
174 // the thread that called Run.
Gabriel Charette066702b2019-02-28 18:12:55175 //
Francois Dorayb61fcc112020-03-25 21:11:58176 // It isn't necessary to call this during normal execution, as the pump wakes
Etienne Pierre-doray2163f3012020-04-02 21:37:14177 // up as requested by the return value of DoWork().
Francois Dorayb61fcc112020-03-25 21:11:58178 // TODO(crbug.com/885371): Determine if this must be called to ensure that
179 // delayed tasks run when a message pump outside the control of Run is
180 // entered.
[email protected]7e7fab42010-11-06 22:23:29181 virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) = 0;
[email protected]57cd3d22014-06-05 19:36:20182
183 // Sets the timer slack to the specified value.
184 virtual void SetTimerSlack(TimerSlack timer_slack);
[email protected]295039bd2008-08-15 04:32:57185};
186
187} // namespace base
188
[email protected]59e69e742013-06-18 20:27:52189#endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_