1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <memory> 9*6777b538SAndroid Build Coastguard Worker #include <utility> 10*6777b538SAndroid Build Coastguard Worker 11*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h" 12*6777b538SAndroid Build Coastguard Worker #include "base/check.h" 13*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h" 14*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr_exclusion.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/message_loop/message_pump_type.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/sequence_checker.h" 17*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h" 18*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h" 19*6777b538SAndroid Build Coastguard Worker 20*6777b538SAndroid Build Coastguard Worker namespace base { 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard Worker class TimeTicks; 23*6777b538SAndroid Build Coastguard Worker 24*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT MessagePump { 25*6777b538SAndroid Build Coastguard Worker public: 26*6777b538SAndroid Build Coastguard Worker using MessagePumpFactory = std::unique_ptr<MessagePump>(); 27*6777b538SAndroid Build Coastguard Worker // Uses the given base::MessagePumpFactory to override the default MessagePump 28*6777b538SAndroid Build Coastguard Worker // implementation for 'MessagePumpType::UI'. May only be called once. 29*6777b538SAndroid Build Coastguard Worker static void OverrideMessagePumpForUIFactory(MessagePumpFactory* factory); 30*6777b538SAndroid Build Coastguard Worker 31*6777b538SAndroid Build Coastguard Worker // Returns true if the MessagePumpForUI has been overidden. 32*6777b538SAndroid Build Coastguard Worker static bool IsMessagePumpForUIFactoryOveridden(); 33*6777b538SAndroid Build Coastguard Worker 34*6777b538SAndroid Build Coastguard Worker static void InitializeFeatures(); 35*6777b538SAndroid Build Coastguard Worker 36*6777b538SAndroid Build Coastguard Worker // Manage the state of |kAlignWakeUps| and the leeway of the process. 37*6777b538SAndroid Build Coastguard Worker static void OverrideAlignWakeUpsState(bool enabled, TimeDelta leeway); 38*6777b538SAndroid Build Coastguard Worker static void ResetAlignWakeUpsState(); 39*6777b538SAndroid Build Coastguard Worker static bool GetAlignWakeUpsEnabled(); 40*6777b538SAndroid Build Coastguard Worker static TimeDelta GetLeewayIgnoringThreadOverride(); 41*6777b538SAndroid Build Coastguard Worker static TimeDelta GetLeewayForCurrentThread(); 42*6777b538SAndroid Build Coastguard Worker 43*6777b538SAndroid Build Coastguard Worker // Creates the default MessagePump based on |type|. Caller owns return value. 44*6777b538SAndroid Build Coastguard Worker static std::unique_ptr<MessagePump> Create(MessagePumpType type); 45*6777b538SAndroid Build Coastguard Worker 46*6777b538SAndroid Build Coastguard Worker // Please see the comments above the Run method for an illustration of how 47*6777b538SAndroid Build Coastguard Worker // these delegate methods are used. 48*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT Delegate { 49*6777b538SAndroid Build Coastguard Worker public: 50*6777b538SAndroid Build Coastguard Worker virtual ~Delegate() = default; 51*6777b538SAndroid Build Coastguard Worker 52*6777b538SAndroid Build Coastguard Worker struct NextWorkInfo { 53*6777b538SAndroid Build Coastguard Worker // Helper to extract a TimeDelta for pumps that need a 54*6777b538SAndroid Build Coastguard Worker // timeout-till-next-task. remaining_delayNextWorkInfo55*6777b538SAndroid Build Coastguard Worker TimeDelta remaining_delay() const { 56*6777b538SAndroid Build Coastguard Worker DCHECK(!delayed_run_time.is_null() && !delayed_run_time.is_max()); 57*6777b538SAndroid Build Coastguard Worker DCHECK_GE(TimeTicks::Now(), recent_now); 58*6777b538SAndroid Build Coastguard Worker return delayed_run_time - recent_now; 59*6777b538SAndroid Build Coastguard Worker } 60*6777b538SAndroid Build Coastguard Worker 61*6777b538SAndroid Build Coastguard Worker // Helper to verify if the next task is ready right away. is_immediateNextWorkInfo62*6777b538SAndroid Build Coastguard Worker bool is_immediate() const { return delayed_run_time.is_null(); } 63*6777b538SAndroid Build Coastguard Worker 64*6777b538SAndroid Build Coastguard Worker // The next PendingTask's |delayed_run_time|. is_null() if there's extra 65*6777b538SAndroid Build Coastguard Worker // work to run immediately. is_max() if there are no more immediate nor 66*6777b538SAndroid Build Coastguard Worker // delayed tasks. 67*6777b538SAndroid Build Coastguard Worker TimeTicks delayed_run_time; 68*6777b538SAndroid Build Coastguard Worker 69*6777b538SAndroid Build Coastguard Worker // |leeway| determines the preferred time range for scheduling 70*6777b538SAndroid Build Coastguard Worker // work. A larger leeway provides more freedom to schedule work at 71*6777b538SAndroid Build Coastguard Worker // an optimal time for power consumption. This field is ignored 72*6777b538SAndroid Build Coastguard Worker // for immediate work. 73*6777b538SAndroid Build Coastguard Worker TimeDelta leeway; 74*6777b538SAndroid Build Coastguard Worker 75*6777b538SAndroid Build Coastguard Worker // A recent view of TimeTicks::Now(). Only valid if |delayed_run_time| 76*6777b538SAndroid Build Coastguard Worker // isn't null nor max. MessagePump impls should use remaining_delay() 77*6777b538SAndroid Build Coastguard Worker // instead of resampling Now() if they wish to sleep for a TimeDelta. 78*6777b538SAndroid Build Coastguard Worker TimeTicks recent_now; 79*6777b538SAndroid Build Coastguard Worker 80*6777b538SAndroid Build Coastguard Worker // If true, native messages should be processed before executing more work 81*6777b538SAndroid Build Coastguard Worker // from the Delegate. This is an optional hint; not all message pumps 82*6777b538SAndroid Build Coastguard Worker // implement this. 83*6777b538SAndroid Build Coastguard Worker bool yield_to_native = false; 84*6777b538SAndroid Build Coastguard Worker }; 85*6777b538SAndroid Build Coastguard Worker 86*6777b538SAndroid Build Coastguard Worker // Executes an immediate task or a ripe delayed task. Returns information 87*6777b538SAndroid Build Coastguard Worker // about when DoWork() should be called again. If the returned NextWorkInfo 88*6777b538SAndroid Build Coastguard Worker // is_immediate(), DoWork() must be invoked again shortly. Else, DoWork() 89*6777b538SAndroid Build Coastguard Worker // must be invoked at |NextWorkInfo::delayed_run_time| or when 90*6777b538SAndroid Build Coastguard Worker // ScheduleWork() is invoked, whichever comes first. Redundant/spurious 91*6777b538SAndroid Build Coastguard Worker // invocations of DoWork() outside of those requirements are tolerated. 92*6777b538SAndroid Build Coastguard Worker // DoIdleWork() will not be called so long as this returns a NextWorkInfo 93*6777b538SAndroid Build Coastguard Worker // which is_immediate(). 94*6777b538SAndroid Build Coastguard Worker virtual NextWorkInfo DoWork() = 0; 95*6777b538SAndroid Build Coastguard Worker 96*6777b538SAndroid Build Coastguard Worker // Called from within Run just before the message pump goes to sleep. 97*6777b538SAndroid Build Coastguard Worker // Returns true to indicate that idle work was done; in which case Run() 98*6777b538SAndroid Build Coastguard Worker // should resume with calling DoWork(). Returning false means the pump 99*6777b538SAndroid Build Coastguard Worker // should now wait. 100*6777b538SAndroid Build Coastguard Worker virtual bool DoIdleWork() = 0; 101*6777b538SAndroid Build Coastguard Worker 102*6777b538SAndroid Build Coastguard Worker class ScopedDoWorkItem { 103*6777b538SAndroid Build Coastguard Worker public: ScopedDoWorkItem()104*6777b538SAndroid Build Coastguard Worker ScopedDoWorkItem() : outer_(nullptr), work_item_depth_(0) {} 105*6777b538SAndroid Build Coastguard Worker ~ScopedDoWorkItem()106*6777b538SAndroid Build Coastguard Worker ~ScopedDoWorkItem() { 107*6777b538SAndroid Build Coastguard Worker if (outer_) { 108*6777b538SAndroid Build Coastguard Worker outer_->OnEndWorkItem(work_item_depth_); 109*6777b538SAndroid Build Coastguard Worker } 110*6777b538SAndroid Build Coastguard Worker } 111*6777b538SAndroid Build Coastguard Worker ScopedDoWorkItem(ScopedDoWorkItem && rhs)112*6777b538SAndroid Build Coastguard Worker ScopedDoWorkItem(ScopedDoWorkItem&& rhs) 113*6777b538SAndroid Build Coastguard Worker : outer_(std::exchange(rhs.outer_, nullptr)), 114*6777b538SAndroid Build Coastguard Worker work_item_depth_(rhs.work_item_depth_) {} 115*6777b538SAndroid Build Coastguard Worker ScopedDoWorkItem& operator=(ScopedDoWorkItem&& rhs) { 116*6777b538SAndroid Build Coastguard Worker // We should only ever go from an empty ScopedDoWorkItem to an 117*6777b538SAndroid Build Coastguard Worker // initialized one, or from an initialized one to an empty one. 118*6777b538SAndroid Build Coastguard Worker CHECK_NE(IsNull(), rhs.IsNull()); 119*6777b538SAndroid Build Coastguard Worker // Since we're overwriting this ScopedDoWorkItem, we need to record its 120*6777b538SAndroid Build Coastguard Worker // destruction. 121*6777b538SAndroid Build Coastguard Worker if (outer_) { 122*6777b538SAndroid Build Coastguard Worker outer_->OnEndWorkItem(work_item_depth_); 123*6777b538SAndroid Build Coastguard Worker } 124*6777b538SAndroid Build Coastguard Worker 125*6777b538SAndroid Build Coastguard Worker work_item_depth_ = rhs.work_item_depth_; 126*6777b538SAndroid Build Coastguard Worker outer_ = std::exchange(rhs.outer_, nullptr); 127*6777b538SAndroid Build Coastguard Worker return *this; 128*6777b538SAndroid Build Coastguard Worker } 129*6777b538SAndroid Build Coastguard Worker IsNull()130*6777b538SAndroid Build Coastguard Worker bool IsNull() { return !outer_; } 131*6777b538SAndroid Build Coastguard Worker 132*6777b538SAndroid Build Coastguard Worker private: 133*6777b538SAndroid Build Coastguard Worker friend Delegate; 134*6777b538SAndroid Build Coastguard Worker ScopedDoWorkItem(Delegate * outer)135*6777b538SAndroid Build Coastguard Worker explicit ScopedDoWorkItem(Delegate* outer) : outer_(outer) { 136*6777b538SAndroid Build Coastguard Worker outer_->OnBeginWorkItem(); 137*6777b538SAndroid Build Coastguard Worker work_item_depth_ = outer_->RunDepth(); 138*6777b538SAndroid Build Coastguard Worker } 139*6777b538SAndroid Build Coastguard Worker 140*6777b538SAndroid Build Coastguard Worker // `outer_` is not a raw_ptr<...> for performance reasons (based on 141*6777b538SAndroid Build Coastguard Worker // analysis of sampling profiler data and tab_search:top100:2020). 142*6777b538SAndroid Build Coastguard Worker RAW_PTR_EXCLUSION Delegate* outer_; 143*6777b538SAndroid Build Coastguard Worker 144*6777b538SAndroid Build Coastguard Worker // Records the run level at which this DoWorkItem was created to allow 145*6777b538SAndroid Build Coastguard Worker // detection of exits of nested loops. 146*6777b538SAndroid Build Coastguard Worker int work_item_depth_; 147*6777b538SAndroid Build Coastguard Worker }; 148*6777b538SAndroid Build Coastguard Worker 149*6777b538SAndroid Build Coastguard Worker // Called before a unit of work is executed. This allows reports 150*6777b538SAndroid Build Coastguard Worker // about individual units of work to be produced. The unit of work ends when 151*6777b538SAndroid Build Coastguard Worker // the returned ScopedDoWorkItem goes out of scope. 152*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/851163): Place calls for all platforms. Without this, some 153*6777b538SAndroid Build Coastguard Worker // state like the top-level "ThreadController active" trace event will not 154*6777b538SAndroid Build Coastguard Worker // be correct when work is performed. BeginWorkItem()155*6777b538SAndroid Build Coastguard Worker [[nodiscard]] ScopedDoWorkItem BeginWorkItem() { 156*6777b538SAndroid Build Coastguard Worker return ScopedDoWorkItem(this); 157*6777b538SAndroid Build Coastguard Worker } 158*6777b538SAndroid Build Coastguard Worker 159*6777b538SAndroid Build Coastguard Worker // Called before the message pump starts waiting for work. This indicates 160*6777b538SAndroid Build Coastguard Worker // that the message pump is idle (out of application work and ideally out of 161*6777b538SAndroid Build Coastguard Worker // native work -- if it can tell). 162*6777b538SAndroid Build Coastguard Worker virtual void BeforeWait() = 0; 163*6777b538SAndroid Build Coastguard Worker 164*6777b538SAndroid Build Coastguard Worker // May be called when starting to process native work and it is guaranteed 165*6777b538SAndroid Build Coastguard Worker // that DoWork() will be called again before sleeping. Allows the delegate 166*6777b538SAndroid Build Coastguard Worker // to skip unnecessary ScheduleWork() calls. 167*6777b538SAndroid Build Coastguard Worker virtual void BeginNativeWorkBeforeDoWork() = 0; 168*6777b538SAndroid Build Coastguard Worker 169*6777b538SAndroid Build Coastguard Worker // Returns the nesting level at which the Delegate is currently running. 170*6777b538SAndroid Build Coastguard Worker virtual int RunDepth() = 0; 171*6777b538SAndroid Build Coastguard Worker 172*6777b538SAndroid Build Coastguard Worker private: 173*6777b538SAndroid Build Coastguard Worker // Called upon entering/exiting a ScopedDoWorkItem. 174*6777b538SAndroid Build Coastguard Worker virtual void OnBeginWorkItem() = 0; 175*6777b538SAndroid Build Coastguard Worker virtual void OnEndWorkItem(int work_item_depth) = 0; 176*6777b538SAndroid Build Coastguard Worker }; 177*6777b538SAndroid Build Coastguard Worker 178*6777b538SAndroid Build Coastguard Worker MessagePump(); 179*6777b538SAndroid Build Coastguard Worker virtual ~MessagePump(); 180*6777b538SAndroid Build Coastguard Worker 181*6777b538SAndroid Build Coastguard Worker // The Run method is called to enter the message pump's run loop. 182*6777b538SAndroid Build Coastguard Worker // 183*6777b538SAndroid Build Coastguard Worker // Within the method, the message pump is responsible for processing native 184*6777b538SAndroid Build Coastguard Worker // messages as well as for giving cycles to the delegate periodically. The 185*6777b538SAndroid Build Coastguard Worker // message pump should take care to mix delegate callbacks with native message 186*6777b538SAndroid Build Coastguard Worker // processing so neither type of event starves the other of cycles. Each call 187*6777b538SAndroid Build Coastguard Worker // to a delegate function is considered the beginning of a new "unit of work". 188*6777b538SAndroid Build Coastguard Worker // 189*6777b538SAndroid Build Coastguard Worker // The anatomy of a typical run loop: 190*6777b538SAndroid Build Coastguard Worker // 191*6777b538SAndroid Build Coastguard Worker // for (;;) { 192*6777b538SAndroid Build Coastguard Worker // bool did_native_work = false; 193*6777b538SAndroid Build Coastguard Worker // { 194*6777b538SAndroid Build Coastguard Worker // auto scoped_do_work_item = state_->delegate->BeginWorkItem(); 195*6777b538SAndroid Build Coastguard Worker // did_native_work = DoNativeWork(); 196*6777b538SAndroid Build Coastguard Worker // } 197*6777b538SAndroid Build Coastguard Worker // if (should_quit_) 198*6777b538SAndroid Build Coastguard Worker // break; 199*6777b538SAndroid Build Coastguard Worker // 200*6777b538SAndroid Build Coastguard Worker // Delegate::NextWorkInfo next_work_info = delegate->DoWork(); 201*6777b538SAndroid Build Coastguard Worker // if (should_quit_) 202*6777b538SAndroid Build Coastguard Worker // break; 203*6777b538SAndroid Build Coastguard Worker // 204*6777b538SAndroid Build Coastguard Worker // if (did_native_work || next_work_info.is_immediate()) 205*6777b538SAndroid Build Coastguard Worker // continue; 206*6777b538SAndroid Build Coastguard Worker // 207*6777b538SAndroid Build Coastguard Worker // bool did_idle_work = delegate_->DoIdleWork(); 208*6777b538SAndroid Build Coastguard Worker // if (should_quit_) 209*6777b538SAndroid Build Coastguard Worker // break; 210*6777b538SAndroid Build Coastguard Worker // 211*6777b538SAndroid Build Coastguard Worker // if (did_idle_work) 212*6777b538SAndroid Build Coastguard Worker // continue; 213*6777b538SAndroid Build Coastguard Worker // 214*6777b538SAndroid Build Coastguard Worker // WaitForWork(); 215*6777b538SAndroid Build Coastguard Worker // } 216*6777b538SAndroid Build Coastguard Worker // 217*6777b538SAndroid Build Coastguard Worker 218*6777b538SAndroid Build Coastguard Worker // Here, DoNativeWork is some private method of the message pump that is 219*6777b538SAndroid Build Coastguard Worker // responsible for dispatching the next UI message or notifying the next IO 220*6777b538SAndroid Build Coastguard Worker // completion (for example). WaitForWork is a private method that simply 221*6777b538SAndroid Build Coastguard Worker // blocks until there is more work of any type to do. 222*6777b538SAndroid Build Coastguard Worker // 223*6777b538SAndroid Build Coastguard Worker // Notice that the run loop cycles between calling DoNativeWork and DoWork 224*6777b538SAndroid Build Coastguard Worker // methods. This helps ensure that none of these work queues starve the 225*6777b538SAndroid Build Coastguard Worker // others. This is important for message pumps that are used to drive 226*6777b538SAndroid Build Coastguard Worker // animations, for example. 227*6777b538SAndroid Build Coastguard Worker // 228*6777b538SAndroid Build Coastguard Worker // Notice also that after each callout to foreign code, the run loop checks to 229*6777b538SAndroid Build Coastguard Worker // see if it should quit. The Quit method is responsible for setting this 230*6777b538SAndroid Build Coastguard Worker // flag. No further work is done once the quit flag is set. 231*6777b538SAndroid Build Coastguard Worker // 232*6777b538SAndroid Build Coastguard Worker // NOTE 1: Run may be called reentrantly from any of the callouts to foreign 233*6777b538SAndroid Build Coastguard Worker // code (internal work, DoWork, DoIdleWork). As a result, DoWork and 234*6777b538SAndroid Build Coastguard Worker // DoIdleWork must be reentrant. 235*6777b538SAndroid Build Coastguard Worker // 236*6777b538SAndroid Build Coastguard Worker // NOTE 2: Run implementations must arrange for DoWork to be invoked as 237*6777b538SAndroid Build Coastguard Worker // expected if a callout to foreign code enters a message pump outside their 238*6777b538SAndroid Build Coastguard Worker // control. For example, the MessageBox API on Windows pumps UI messages. If 239*6777b538SAndroid Build Coastguard Worker // the MessageBox API is called (indirectly) from within Run, it is expected 240*6777b538SAndroid Build Coastguard Worker // that DoWork will be invoked from within that call in response to 241*6777b538SAndroid Build Coastguard Worker // ScheduleWork or as requested by the last NextWorkInfo returned by DoWork. 242*6777b538SAndroid Build Coastguard Worker // The MessagePump::Delegate may then elect to do nested work or not depending 243*6777b538SAndroid Build Coastguard Worker // on its policy in that context. Regardless of that decision (and return 244*6777b538SAndroid Build Coastguard Worker // value of the nested DoWork() call), DoWork() will be invoked again when the 245*6777b538SAndroid Build Coastguard Worker // nested loop unwinds. 246*6777b538SAndroid Build Coastguard Worker virtual void Run(Delegate* delegate) = 0; 247*6777b538SAndroid Build Coastguard Worker 248*6777b538SAndroid Build Coastguard Worker // Quit immediately from the most recently entered run loop. This method may 249*6777b538SAndroid Build Coastguard Worker // only be used on the thread that called Run. 250*6777b538SAndroid Build Coastguard Worker virtual void Quit() = 0; 251*6777b538SAndroid Build Coastguard Worker 252*6777b538SAndroid Build Coastguard Worker // Schedule a DoWork callback to happen reasonably soon. Does nothing if a 253*6777b538SAndroid Build Coastguard Worker // DoWork callback is already scheduled. Once this call is made, DoWork is 254*6777b538SAndroid Build Coastguard Worker // guaranteed to be called repeatedly at least until it returns a 255*6777b538SAndroid Build Coastguard Worker // non-immediate NextWorkInfo. This call can be expensive and callers should 256*6777b538SAndroid Build Coastguard Worker // attempt not to invoke it again before a non-immediate NextWorkInfo was 257*6777b538SAndroid Build Coastguard Worker // returned from DoWork(). Thread-safe (and callers should avoid holding a 258*6777b538SAndroid Build Coastguard Worker // Lock at all cost while making this call as some platforms' priority 259*6777b538SAndroid Build Coastguard Worker // boosting features have been observed to cause the caller to get descheduled 260*6777b538SAndroid Build Coastguard Worker // : https://crbug.com/890978). 261*6777b538SAndroid Build Coastguard Worker virtual void ScheduleWork() = 0; 262*6777b538SAndroid Build Coastguard Worker 263*6777b538SAndroid Build Coastguard Worker // Schedule a DoWork callback to happen at the specified time, cancelling any 264*6777b538SAndroid Build Coastguard Worker // pending callback scheduled by this method. This method may only be used on 265*6777b538SAndroid Build Coastguard Worker // the thread that called Run. 266*6777b538SAndroid Build Coastguard Worker // 267*6777b538SAndroid Build Coastguard Worker // It isn't necessary to call this during normal execution, as the pump wakes 268*6777b538SAndroid Build Coastguard Worker // up as requested by the return value of DoWork(). 269*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/885371): Determine if this must be called to ensure that 270*6777b538SAndroid Build Coastguard Worker // delayed tasks run when a message pump outside the control of Run is 271*6777b538SAndroid Build Coastguard Worker // entered. 272*6777b538SAndroid Build Coastguard Worker virtual void ScheduleDelayedWork( 273*6777b538SAndroid Build Coastguard Worker const Delegate::NextWorkInfo& next_work_info) = 0; 274*6777b538SAndroid Build Coastguard Worker 275*6777b538SAndroid Build Coastguard Worker // Returns an adjusted |run_time| based on alignment policies of the pump. 276*6777b538SAndroid Build Coastguard Worker virtual TimeTicks AdjustDelayedRunTime(TimeTicks earliest_time, 277*6777b538SAndroid Build Coastguard Worker TimeTicks run_time, 278*6777b538SAndroid Build Coastguard Worker TimeTicks latest_time); 279*6777b538SAndroid Build Coastguard Worker 280*6777b538SAndroid Build Coastguard Worker // Requests the pump to handle either the likely imminent creation (`true`) or 281*6777b538SAndroid Build Coastguard Worker // destruction (`false`) of a native nested loop in which application tasks 282*6777b538SAndroid Build Coastguard Worker // are desired to be run. The pump should override and return `true` if it 283*6777b538SAndroid Build Coastguard Worker // supports this call and has scheduled work in response. The default 284*6777b538SAndroid Build Coastguard Worker // implementation returns `false` and does nothing. 285*6777b538SAndroid Build Coastguard Worker virtual bool HandleNestedNativeLoopWithApplicationTasks( 286*6777b538SAndroid Build Coastguard Worker bool application_tasks_desired); 287*6777b538SAndroid Build Coastguard Worker }; 288*6777b538SAndroid Build Coastguard Worker 289*6777b538SAndroid Build Coastguard Worker } // namespace base 290*6777b538SAndroid Build Coastguard Worker 291*6777b538SAndroid Build Coastguard Worker #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_ 292