1 // Copyright 2014 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 5 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_SCHEDULER_IMPL_H_ 6 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_SCHEDULER_IMPL_H_ 7 8 #include <map> 9 #include <memory> 10 #include <random> 11 #include <stack> 12 13 #include "base/atomicops.h" 14 #include "base/gtest_prod_util.h" 15 #include "base/macros.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/metrics/single_sample_metrics.h" 18 #include "base/optional.h" 19 #include "base/profiler/sample_metadata.h" 20 #include "base/single_thread_task_runner.h" 21 #include "base/synchronization/lock.h" 22 #include "base/task/sequence_manager/task_queue.h" 23 #include "base/task/sequence_manager/task_time_observer.h" 24 #include "base/trace_event/trace_log.h" 25 #include "build/build_config.h" 26 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" 27 #include "third_party/blink/renderer/platform/platform_export.h" 28 #include "third_party/blink/renderer/platform/scheduler/common/idle_helper.h" 29 #include "third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h" 30 #include "third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h" 31 #include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h" 32 #include "third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h" 33 #include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h" 34 #include "third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h" 35 #include "third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h" 36 #include "third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h" 37 #include "third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h" 38 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h" 39 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h" 40 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h" 41 #include "third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h" 42 #include "third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.h" 43 #include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h" 44 #include "third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h" 45 #include "third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals.h" 46 #include "third_party/blink/renderer/platform/scheduler/main_thread/use_case.h" 47 #include "third_party/blink/renderer/platform/scheduler/main_thread/user_model.h" 48 #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h" 49 #include "third_party/blink/renderer/platform/scheduler/public/rail_mode_observer.h" 50 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" 51 #include "third_party/blink/renderer/platform/wtf/hash_set.h" 52 #include "third_party/blink/renderer/platform/wtf/vector.h" 53 54 namespace base { 55 56 class TaskObserver; 57 58 namespace trace_event { 59 class ConvertableToTraceFormat; 60 } 61 } // namespace base 62 63 namespace blink { 64 namespace scheduler { 65 namespace frame_scheduler_impl_unittest { 66 class FrameSchedulerImplTest; 67 } // namespace frame_scheduler_impl_unittest 68 namespace main_thread_scheduler_impl_unittest { 69 class MainThreadSchedulerImplForTest; 70 class MainThreadSchedulerImplTest; 71 class MockPageSchedulerImpl; 72 FORWARD_DECLARE_TEST(MainThreadSchedulerImplTest, ShouldIgnoreTaskForUkm); 73 FORWARD_DECLARE_TEST(MainThreadSchedulerImplTest, Tracing); 74 FORWARD_DECLARE_TEST(MainThreadSchedulerImplTest, 75 LogIpcsPostedToDocumentsInBackForwardCache); 76 } // namespace main_thread_scheduler_impl_unittest 77 class AgentGroupSchedulerImpl; 78 class FrameSchedulerImpl; 79 class PageSchedulerImpl; 80 class TaskQueueThrottler; 81 class WebRenderWidgetSchedulingState; 82 83 class PLATFORM_EXPORT MainThreadSchedulerImpl 84 : public ThreadSchedulerImpl, 85 public AgentSchedulingStrategy::Delegate, 86 public IdleHelper::Delegate, 87 public MainThreadSchedulerHelper::Observer, 88 public RenderWidgetSignals::Observer, 89 public base::trace_event::TraceLog::AsyncEnabledStateObserver { 90 public: 91 // Don't use except for tracing. 92 struct TaskDescriptionForTracing { 93 TaskType task_type; 94 base::Optional<MainThreadTaskQueue::QueueType> queue_type; 95 96 // Required in order to wrap in TraceableState. 97 constexpr bool operator!=(const TaskDescriptionForTracing& rhs) const { 98 return task_type != rhs.task_type || queue_type != rhs.queue_type; 99 } 100 }; 101 102 struct SchedulingSettings { 103 SchedulingSettings(); 104 105 // Background page priority experiment (crbug.com/848835). 106 bool low_priority_background_page; 107 bool best_effort_background_page; 108 109 // Task and subframe priority experiment (crbug.com/852380). 110 bool low_priority_subframe; 111 bool low_priority_throttleable; 112 bool low_priority_subframe_throttleable; 113 bool low_priority_hidden_frame; 114 115 // Used along with |low_priority_subframe|, |low_priority_throttleable|, 116 // |low_priority_subframe_throttleable|, |low_priority_hidden_frame| 117 // to enable one of these experiments during the loading phase only. 118 bool use_frame_priorities_only_during_loading; 119 120 // Ads priority experiment (crbug.com/856150). 121 bool low_priority_ad_frame; 122 bool best_effort_ad_frame; 123 bool use_adframe_priorities_only_during_loading; 124 125 // Origin type priority experiment (crbug.com/856158). 126 bool low_priority_cross_origin; 127 bool low_priority_cross_origin_only_during_loading; 128 129 // Use resource fetch priority for resource loading tasks 130 // (crbug.com/860545). 131 bool use_resource_fetch_priority; 132 bool use_resource_priorities_only_during_loading; 133 134 // Prioritize compositing and loading tasks until first contentful paint. 135 // (crbug.com/971191) 136 bool prioritize_compositing_and_loading_during_early_loading; 137 138 // Prioritise one BeginMainFrame after an input task. 139 bool prioritize_compositing_after_input; 140 141 // Contains a mapping from net::RequestPriority to TaskQueue::QueuePriority 142 // when use_resource_fetch_priority is enabled. 143 std::array<base::sequence_manager::TaskQueue::QueuePriority, 144 net::RequestPrioritySize::NUM_PRIORITIES> 145 net_to_blink_priority; 146 }; 147 148 static const char* UseCaseToString(UseCase use_case); 149 static const char* RAILModeToString(RAILMode rail_mode); 150 static const char* VirtualTimePolicyToString( 151 PageScheduler::VirtualTimePolicy); 152 153 // If |initial_virtual_time| is specified then the scheduler will be created 154 // with virtual time enabled and paused with base::Time will be overridden to 155 // start at |initial_virtual_time|. 156 MainThreadSchedulerImpl( 157 std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager, 158 base::Optional<base::Time> initial_virtual_time); 159 160 ~MainThreadSchedulerImpl() override; 161 162 // WebThreadScheduler implementation: 163 std::unique_ptr<Thread> CreateMainThread() override; 164 std::unique_ptr<WebWidgetScheduler> CreateWidgetScheduler() override; 165 // Note: this is also shared by the ThreadScheduler interface. 166 scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override; 167 scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner() 168 override; 169 std::unique_ptr<WebRenderWidgetSchedulingState> 170 NewRenderWidgetSchedulingState() override; 171 void WillBeginFrame(const viz::BeginFrameArgs& args) override; 172 void BeginFrameNotExpectedSoon() override; 173 void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override; 174 void DidCommitFrameToCompositor() override; 175 void DidHandleInputEventOnCompositorThread( 176 const WebInputEvent& web_input_event, 177 InputEventState event_state) override; 178 void WillPostInputEventToMainThread( 179 WebInputEvent::Type web_input_event_type, 180 const WebInputEventAttribution& web_input_event_attribution) override; 181 void WillHandleInputEventOnMainThread( 182 WebInputEvent::Type web_input_event_type, 183 const WebInputEventAttribution& web_input_event_attribution) override; 184 void DidHandleInputEventOnMainThread(const WebInputEvent& web_input_event, 185 WebInputEventResult result) override; 186 void DidAnimateForInputOnCompositorThread() override; 187 void DidScheduleBeginMainFrame() override; 188 void DidRunBeginMainFrame() override; 189 void SetRendererHidden(bool hidden) override; 190 void SetRendererBackgrounded(bool backgrounded) override; 191 void SetSchedulerKeepActive(bool keep_active) override; 192 bool SchedulerKeepActive(); 193 void OnMainFrameRequestedForInput() override; 194 #if defined(OS_ANDROID) 195 void PauseTimersForAndroidWebView() override; 196 void ResumeTimersForAndroidWebView() override; 197 #endif 198 std::unique_ptr<ThreadScheduler::RendererPauseHandle> PauseRenderer() override 199 WARN_UNUSED_RESULT; 200 bool IsHighPriorityWorkAnticipated() override; 201 bool ShouldYieldForHighPriorityWork() override; 202 bool CanExceedIdleDeadlineIfRequired() const override; 203 void AddTaskObserver(base::TaskObserver* task_observer) override; 204 void RemoveTaskObserver(base::TaskObserver* task_observer) override; 205 void Shutdown() override; 206 void SetTopLevelBlameContext( 207 base::trace_event::BlameContext* blame_context) override; 208 void AddRAILModeObserver(RAILModeObserver* observer) override; 209 void RemoveRAILModeObserver(RAILModeObserver const* observer) override; 210 void SetRendererProcessType(WebRendererProcessType type) override; 211 Vector<WebInputEventAttribution> GetPendingUserInputInfo( 212 bool include_continuous) const override; 213 bool IsBeginMainFrameScheduled() const override; 214 215 // ThreadScheduler implementation: 216 void PostIdleTask(const base::Location&, Thread::IdleTask) override; 217 void PostNonNestableIdleTask(const base::Location&, 218 Thread::IdleTask) override; 219 void PostDelayedIdleTask(const base::Location&, 220 base::TimeDelta delay, 221 Thread::IdleTask) override; 222 scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override; 223 scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override; 224 std::unique_ptr<WebAgentGroupScheduler> CreateAgentGroupScheduler() override; 225 WebAgentGroupScheduler* GetCurrentAgentGroupScheduler() override; 226 void SetCurrentAgentGroupScheduler( 227 WebAgentGroupScheduler* agent_group_scheduler); 228 std::unique_ptr<ThreadScheduler::RendererPauseHandle> PauseScheduler() 229 override; 230 base::TimeTicks MonotonicallyIncreasingVirtualTime() override; 231 WebThreadScheduler* GetWebMainThreadSchedulerForTest() override; AsNonMainThreadScheduler()232 NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override { 233 return nullptr; 234 } 235 236 // Use a separate task runner so that IPC tasks are not logged via the same 237 // task queue that executes them. Otherwise this would result in an infinite 238 // loop of posting and logging to a single queue. 239 scoped_refptr<base::SingleThreadTaskRunner> BackForwardCacheIpcTrackingTaskRunner()240 BackForwardCacheIpcTrackingTaskRunner() { 241 return back_forward_cache_ipc_tracking_task_runner_; 242 } 243 244 // WebThreadScheduler implementation: 245 scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override; 246 247 // The following functions are defined in both WebThreadScheduler and 248 // ThreadScheduler, and have the same function signatures -- see above. 249 // This class implements those functions for both base classes. 250 // 251 // void Shutdown() override; 252 // 253 // TODO(yutak): Reduce the overlaps and simplify. 254 255 // RenderWidgetSignals::Observer implementation: 256 void SetAllRenderWidgetsHidden(bool hidden) override; 257 void SetHasVisibleRenderWidgetWithTouchHandler( 258 bool has_visible_render_widget_with_touch_handler) override; 259 260 // SchedulerHelper::Observer implementation: 261 void OnBeginNestedRunLoop() override; 262 void OnExitNestedRunLoop() override; 263 264 // ThreadSchedulerImpl implementation: 265 scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner() override; 266 scoped_refptr<base::SingleThreadTaskRunner> ControlTaskRunner() override; 267 void RegisterTimeDomain( 268 base::sequence_manager::TimeDomain* time_domain) override; 269 void UnregisterTimeDomain( 270 base::sequence_manager::TimeDomain* time_domain) override; 271 base::sequence_manager::TimeDomain* GetActiveTimeDomain() override; 272 const base::TickClock* GetTickClock() override; 273 274 scoped_refptr<base::SingleThreadTaskRunner> VirtualTimeControlTaskRunner(); 275 276 // Returns a new task queue created with given params. 277 scoped_refptr<MainThreadTaskQueue> NewTaskQueue( 278 const MainThreadTaskQueue::QueueCreationParams& params); 279 280 // Returns a new loading task queue. This queue is intended for tasks related 281 // to resource dispatch, foreground HTML parsing, etc... 282 // Note: Tasks posted to kFrameLoadingControl queues must execute quickly. 283 scoped_refptr<MainThreadTaskQueue> NewLoadingTaskQueue( 284 MainThreadTaskQueue::QueueType queue_type, 285 FrameSchedulerImpl* frame_scheduler); 286 287 // Returns a new throttleable task queue to be used for tests. 288 scoped_refptr<MainThreadTaskQueue> NewThrottleableTaskQueueForTest( 289 FrameSchedulerImpl* frame_scheduler); 290 291 scoped_refptr<base::sequence_manager::TaskQueue> NewTaskQueueForTest(); 292 293 using VirtualTimePolicy = PageScheduler::VirtualTimePolicy; 294 295 using BaseTimeOverridePolicy = 296 AutoAdvancingVirtualTimeDomain::BaseTimeOverridePolicy; 297 298 // Tells the scheduler that all TaskQueues should use virtual time. Depending 299 // on the initial time, picks the policy to be either overriding or not. 300 base::TimeTicks EnableVirtualTime(); 301 302 // Tells the scheduler that all TaskQueues should use virtual time. Returns 303 // the base::TimeTicks that virtual time offsets will be relative to. 304 base::TimeTicks EnableVirtualTime(BaseTimeOverridePolicy policy); 305 bool IsVirtualTimeEnabled() const; 306 307 // Migrates all task queues to real time. 308 void DisableVirtualTimeForTesting(); 309 310 // Returns true if virtual time is not paused. 311 bool VirtualTimeAllowedToAdvance() const; 312 void SetVirtualTimePolicy(VirtualTimePolicy virtual_time_policy); 313 void SetInitialVirtualTime(base::Time time); 314 void SetInitialVirtualTimeOffset(base::TimeDelta offset); 315 void SetMaxVirtualTimeTaskStarvationCount(int max_task_starvation_count); 316 base::TimeTicks IncrementVirtualTimePauseCount(); 317 void DecrementVirtualTimePauseCount(); 318 void MaybeAdvanceVirtualTime(base::TimeTicks new_virtual_time); 319 320 void RemoveAgentGroupScheduler(AgentGroupSchedulerImpl*); 321 void AddPageScheduler(PageSchedulerImpl*); 322 void RemovePageScheduler(PageSchedulerImpl*); 323 324 void OnFrameAdded(const FrameSchedulerImpl& frame_scheduler); 325 void OnFrameRemoved(const FrameSchedulerImpl& frame_scheduler); 326 agent_scheduling_strategy()327 AgentSchedulingStrategy& agent_scheduling_strategy() { 328 return *agent_scheduling_strategy_; 329 } 330 331 // Called by an associated PageScheduler when frozen or resumed. 332 void OnPageFrozen(); 333 void OnPageResumed(); 334 335 void AddTaskTimeObserver(base::sequence_manager::TaskTimeObserver*); 336 void RemoveTaskTimeObserver(base::sequence_manager::TaskTimeObserver*); 337 338 // Snapshots this MainThreadSchedulerImpl for tracing. 339 void CreateTraceEventObjectSnapshot() const; 340 341 // Called when one of associated page schedulers has changed audio state. 342 void OnAudioStateChanged(); 343 344 // Tells the scheduler that a provisional load has committed. Must be called 345 // from the main thread. 346 void DidStartProvisionalLoad(bool is_main_frame); 347 348 // Tells the scheduler that a provisional load has committed. The scheduler 349 // may reset the task cost estimators and the UserModel. Must be called from 350 // the main thread. 351 void DidCommitProvisionalLoad(bool is_web_history_inert_commit, 352 bool is_reload, 353 bool is_main_frame); 354 355 // Note that the main's thread policy should be upto date to compute 356 // the correct priority. 357 base::sequence_manager::TaskQueue::QueuePriority ComputePriority( 358 MainThreadTaskQueue* task_queue) const; 359 360 // Test helpers. 361 MainThreadSchedulerHelper* GetSchedulerHelperForTesting(); 362 IdleTimeEstimator* GetIdleTimeEstimatorForTesting(); 363 base::TimeTicks CurrentIdleTaskDeadlineForTesting() const; 364 void RunIdleTasksForTesting(base::OnceClosure callback); 365 void EndIdlePeriodForTesting(base::OnceClosure callback, 366 base::TimeTicks time_remaining); 367 bool PolicyNeedsUpdateForTesting(); 368 369 const base::TickClock* tick_clock() const; 370 real_time_domain()371 base::sequence_manager::TimeDomain* real_time_domain() const { 372 return helper_.real_time_domain(); 373 } 374 375 AutoAdvancingVirtualTimeDomain* GetVirtualTimeDomain(); 376 task_queue_throttler()377 TaskQueueThrottler* task_queue_throttler() const { 378 return task_queue_throttler_.get(); 379 } 380 381 // Virtual for test. 382 virtual void OnMainFramePaint(); 383 void OnMainFrameLoad(const FrameSchedulerImpl& frame_scheduler); 384 void OnAgentStrategyUpdated(); 385 386 void OnShutdownTaskQueue(const scoped_refptr<MainThreadTaskQueue>& queue); 387 388 void OnTaskStarted( 389 MainThreadTaskQueue* queue, 390 const base::sequence_manager::Task& task, 391 const base::sequence_manager::TaskQueue::TaskTiming& task_timing); 392 393 void OnTaskCompleted( 394 base::WeakPtr<MainThreadTaskQueue> queue, 395 const base::sequence_manager::Task& task, 396 base::sequence_manager::TaskQueue::TaskTiming* task_timing, 397 base::sequence_manager::LazyNow* lazy_now); 398 399 void UpdateIpcTracking(); 400 void SetOnIPCTaskPostedWhileInBackForwardCacheIfNeeded(); 401 void OnIPCTaskPostedWhileInAllPagesBackForwardCache( 402 uint32_t ipc_hash, 403 const char* ipc_interface_name); 404 void DetachOnIPCTaskPostedWhileInBackForwardCacheHandler(); 405 406 bool IsAudioPlaying() const; 407 408 // base::trace_event::TraceLog::EnabledStateObserver implementation: 409 void OnTraceLogEnabled() override; 410 void OnTraceLogDisabled() override; 411 412 UseCase current_use_case() const; 413 414 const SchedulingSettings& scheduling_settings() const; 415 416 void SetPrioritizeCompositingAfterInput( 417 bool prioritize_compositing_after_input); 418 419 void OnCompositorPriorityExperimentUpdateCompositorPriority(); 420 421 // Allow places in the scheduler to do some work after the current task. 422 // The primary use case here is batching – to allow updates to be processed 423 // only once per task. 424 void ExecuteAfterCurrentTask(base::OnceClosure on_completion_task); 425 426 base::WeakPtr<MainThreadSchedulerImpl> GetWeakPtr(); 427 compositor_priority()428 base::sequence_manager::TaskQueue::QueuePriority compositor_priority() const { 429 return main_thread_only().compositor_priority; 430 } 431 should_prioritize_loading_with_compositing()432 bool should_prioritize_loading_with_compositing() const { 433 return main_thread_only() 434 .current_policy.should_prioritize_loading_with_compositing(); 435 } 436 main_thread_compositing_is_fast()437 bool main_thread_compositing_is_fast() const { 438 return main_thread_only().main_thread_compositing_is_fast; 439 } 440 find_in_page_priority()441 QueuePriority find_in_page_priority() const { 442 return main_thread_only().current_policy.find_in_page_priority(); 443 } 444 445 protected: 446 scoped_refptr<MainThreadTaskQueue> ControlTaskQueue(); 447 scoped_refptr<MainThreadTaskQueue> DefaultTaskQueue(); 448 scoped_refptr<MainThreadTaskQueue> CompositorTaskQueue(); 449 scoped_refptr<MainThreadTaskQueue> V8TaskQueue(); 450 // A control task queue which also respects virtual time. Only available if 451 // virtual time has been enabled. 452 scoped_refptr<MainThreadTaskQueue> VirtualTimeControlTaskQueue(); 453 454 // `current_use_case` will be overwritten by the next call to UpdatePolicy. 455 // Thus, this function should be only used for testing purposes. SetCurrentUseCaseForTest(UseCase use_case)456 void SetCurrentUseCaseForTest(UseCase use_case) { 457 main_thread_only().current_use_case = use_case; 458 } 459 460 void SetHaveSeenABlockingGestureForTesting(bool status); 461 462 virtual void PerformMicrotaskCheckpoint(); 463 464 private: 465 friend class WebRenderWidgetSchedulingState; 466 friend class MainThreadMetricsHelper; 467 468 friend class MainThreadMetricsHelperTest; 469 friend class frame_scheduler_impl_unittest::FrameSchedulerImplTest; 470 friend class main_thread_scheduler_impl_unittest:: 471 MainThreadSchedulerImplForTest; 472 friend class main_thread_scheduler_impl_unittest::MockPageSchedulerImpl; 473 friend class main_thread_scheduler_impl_unittest::MainThreadSchedulerImplTest; 474 475 friend class CompositorPriorityExperiments; 476 friend class FindInPageBudgetPoolController; 477 478 FRIEND_TEST_ALL_PREFIXES( 479 main_thread_scheduler_impl_unittest::MainThreadSchedulerImplTest, 480 ShouldIgnoreTaskForUkm); 481 FRIEND_TEST_ALL_PREFIXES( 482 main_thread_scheduler_impl_unittest::MainThreadSchedulerImplTest, 483 Tracing); 484 FRIEND_TEST_ALL_PREFIXES( 485 main_thread_scheduler_impl_unittest::MainThreadSchedulerImplTest, 486 LogIpcsPostedToDocumentsInBackForwardCache); 487 488 enum class TimeDomainType { 489 kReal, 490 kVirtual, 491 }; 492 493 static const char* TimeDomainTypeToString(TimeDomainType domain_type); 494 495 void AddAgentGroupScheduler(AgentGroupSchedulerImpl*); 496 497 bool IsAnyMainFrameWaitingForFirstContentfulPaint() const; 498 bool IsAnyMainFrameWaitingForFirstMeaningfulPaint() const; 499 500 class Policy { 501 DISALLOW_NEW(); 502 503 public: 504 Policy() = default; 505 ~Policy() = default; 506 rail_mode()507 RAILMode& rail_mode() { return rail_mode_; } rail_mode()508 RAILMode rail_mode() const { return rail_mode_; } 509 should_disable_throttling()510 bool& should_disable_throttling() { return should_disable_throttling_; } should_disable_throttling()511 bool should_disable_throttling() const { 512 return should_disable_throttling_; 513 } 514 frozen_when_backgrounded()515 bool& frozen_when_backgrounded() { return frozen_when_backgrounded_; } frozen_when_backgrounded()516 bool frozen_when_backgrounded() const { return frozen_when_backgrounded_; } 517 should_prioritize_loading_with_compositing()518 bool& should_prioritize_loading_with_compositing() { 519 return should_prioritize_loading_with_compositing_; 520 } should_prioritize_loading_with_compositing()521 bool should_prioritize_loading_with_compositing() const { 522 return should_prioritize_loading_with_compositing_; 523 } 524 should_freeze_compositor_task_queue()525 bool& should_freeze_compositor_task_queue() { 526 return should_freeze_compositor_task_queue_; 527 } should_freeze_compositor_task_queue()528 bool should_freeze_compositor_task_queue() const { 529 return should_freeze_compositor_task_queue_; 530 } 531 should_defer_task_queues()532 bool& should_defer_task_queues() { return should_defer_task_queues_; } should_defer_task_queues()533 bool should_defer_task_queues() const { return should_defer_task_queues_; } 534 should_pause_task_queues()535 bool& should_pause_task_queues() { return should_pause_task_queues_; } should_pause_task_queues()536 bool should_pause_task_queues() const { return should_pause_task_queues_; } 537 use_virtual_time()538 bool& use_virtual_time() { return use_virtual_time_; } use_virtual_time()539 bool use_virtual_time() const { return use_virtual_time_; } 540 should_pause_task_queues_for_android_webview()541 bool& should_pause_task_queues_for_android_webview() { 542 return should_pause_task_queues_for_android_webview_; 543 } should_pause_task_queues_for_android_webview()544 bool should_pause_task_queues_for_android_webview() const { 545 return should_pause_task_queues_for_android_webview_; 546 } 547 find_in_page_priority()548 base::sequence_manager::TaskQueue::QueuePriority& find_in_page_priority() { 549 return find_in_page_priority_; 550 } find_in_page_priority()551 base::sequence_manager::TaskQueue::QueuePriority find_in_page_priority() 552 const { 553 return find_in_page_priority_; 554 } 555 use_case()556 UseCase& use_case() { return use_case_; } use_case()557 UseCase use_case() const { return use_case_; } 558 559 bool operator==(const Policy& other) const { 560 return rail_mode_ == other.rail_mode_ && 561 should_disable_throttling_ == other.should_disable_throttling_ && 562 frozen_when_backgrounded_ == other.frozen_when_backgrounded_ && 563 should_prioritize_loading_with_compositing_ == 564 other.should_prioritize_loading_with_compositing_ && 565 should_freeze_compositor_task_queue_ == 566 other.should_freeze_compositor_task_queue_ && 567 should_defer_task_queues_ == other.should_defer_task_queues_ && 568 should_pause_task_queues_ == other.should_pause_task_queues_ && 569 use_virtual_time_ == other.use_virtual_time_ && 570 should_pause_task_queues_for_android_webview_ == 571 other.should_pause_task_queues_for_android_webview_ && 572 find_in_page_priority_ == other.find_in_page_priority_ && 573 use_case_ == other.use_case_; 574 } 575 576 void AsValueInto(base::trace_event::TracedValue* state) const; 577 578 bool IsQueueEnabled(MainThreadTaskQueue* task_queue) const; 579 580 TimeDomainType GetTimeDomainType() const; 581 582 private: 583 RAILMode rail_mode_{RAILMode::kAnimation}; 584 bool should_disable_throttling_{false}; 585 bool frozen_when_backgrounded_{false}; 586 bool should_prioritize_loading_with_compositing_{false}; 587 bool should_freeze_compositor_task_queue_{false}; 588 bool should_defer_task_queues_{false}; 589 bool should_pause_task_queues_{false}; 590 bool use_virtual_time_{false}; 591 bool should_pause_task_queues_for_android_webview_{false}; 592 593 base::sequence_manager::TaskQueue::QueuePriority find_in_page_priority_{ 594 FindInPageBudgetPoolController::kFindInPageBudgetNotExhaustedPriority}; 595 596 UseCase use_case_{UseCase::kNone}; 597 }; 598 599 class TaskDurationMetricTracker; 600 601 class RendererPauseHandleImpl : public ThreadScheduler::RendererPauseHandle { 602 public: 603 explicit RendererPauseHandleImpl(MainThreadSchedulerImpl* scheduler); 604 ~RendererPauseHandleImpl() override; 605 606 private: 607 MainThreadSchedulerImpl* scheduler_; // NOT OWNED 608 }; 609 610 // AgentSchedulingStrategy::Delegate implementation: 611 void OnSetTimer(const FrameSchedulerImpl& frame_scheduler, 612 base::TimeDelta delay) override; 613 614 // IdleHelper::Delegate implementation: 615 bool CanEnterLongIdlePeriod( 616 base::TimeTicks now, 617 base::TimeDelta* next_long_idle_period_delay_out) override; IsNotQuiescent()618 void IsNotQuiescent() override {} 619 void OnIdlePeriodStarted() override; 620 void OnIdlePeriodEnded() override; 621 void OnPendingTasksChanged(bool has_tasks) override; 622 void OnSafepointEntered() override; 623 void OnSafepointExited() override; 624 625 void DispatchRequestBeginMainFrameNotExpected(bool has_tasks); 626 627 void EndIdlePeriod(); 628 629 // Update a policy which increases priority for the next beginMainFrame after 630 // an input event. 631 void UpdatePrioritizeCompositingAfterInputAfterTaskCompleted( 632 MainThreadTaskQueue* queue); 633 634 // Returns the serialized scheduler state for tracing. 635 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue( 636 base::TimeTicks optional_now) const; 637 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValueLocked( 638 base::TimeTicks optional_now) const; 639 void CreateTraceEventObjectSnapshotLocked() const; 640 641 std::string ToString() const; 642 643 static bool ShouldPrioritizeInputEvent(const WebInputEvent& web_input_event); 644 645 // The amount of time which idle periods can continue being scheduled when the 646 // renderer has been hidden, before going to sleep for good. 647 static const int kEndIdleWhenHiddenDelayMillis = 10000; 648 649 // The amount of time in milliseconds we have to respond to user input as 650 // defined by RAILS. 651 static const int kRailsResponseTimeMillis = 50; 652 653 // The time we should stay in a priority-escalated mode after a call to 654 // DidAnimateForInputOnCompositorThread(). 655 static const int kFlingEscalationLimitMillis = 100; 656 657 // Schedules an immediate PolicyUpdate, if there isn't one already pending and 658 // sets |policy_may_need_update_|. Note |any_thread_lock_| must be 659 // locked. 660 void EnsureUrgentPolicyUpdatePostedOnMainThread( 661 const base::Location& from_here); 662 663 // Update the policy if a new signal has arrived. Must be called from the main 664 // thread. 665 void MaybeUpdatePolicy(); 666 667 // Locks |any_thread_lock_| and updates the scheduler policy. May early 668 // out if the policy is unchanged. Must be called from the main thread. 669 void UpdatePolicy(); 670 671 // Like UpdatePolicy, except it doesn't early out. 672 void ForceUpdatePolicy(); 673 674 enum class UpdateType { 675 kMayEarlyOutIfPolicyUnchanged, 676 kForceUpdate, 677 }; 678 679 // The implementation of UpdatePolicy & ForceUpdatePolicy. It is allowed to 680 // early out if |update_type| is kMayEarlyOutIfPolicyUnchanged. 681 virtual void UpdatePolicyLocked(UpdateType update_type); 682 683 // Helper for computing the use case. |expected_usecase_duration| will be 684 // filled with the amount of time after which the use case should be updated 685 // again. If the duration is zero, a new use case update should not be 686 // scheduled. Must be called with |any_thread_lock_| held. Can be called from 687 // any thread. 688 UseCase ComputeCurrentUseCase( 689 base::TimeTicks now, 690 base::TimeDelta* expected_use_case_duration) const; 691 692 // An input event of some sort happened, the policy may need updating. 693 void UpdateForInputEventOnCompositorThread(const WebInputEvent& event, 694 InputEventState input_event_state); 695 696 // Notifies the per-agent scheduling strategy that an input event occurred. 697 void NotifyAgentSchedulerOnInputEvent(); 698 void OnAgentStrategyDelayPassed(base::WeakPtr<const FrameSchedulerImpl>); 699 700 // The task cost estimators and the UserModel need to be reset upon page 701 // nagigation. This function does that. Must be called from the main thread. 702 void ResetForNavigationLocked(); 703 704 // Estimates the maximum task length that won't cause a jank based on the 705 // current system state. Must be called from the main thread. 706 base::TimeDelta EstimateLongestJankFreeTaskDuration() const; 707 708 // Report an intervention to all WebViews in this process. 709 void BroadcastIntervention(const String& message); 710 711 // Trigger an update to all task queues' priorities, throttling, and 712 // enabled/disabled state based on current policy. When triggered from a 713 // policy update, |previous_policy| should be populated with the pre-update 714 // policy. 715 void UpdateStateForAllTaskQueues(base::Optional<Policy> previous_policy); 716 717 void UpdateTaskQueueState( 718 MainThreadTaskQueue* task_queue, 719 base::sequence_manager::TaskQueue::QueueEnabledVoter* 720 task_queue_enabled_voter, 721 const Policy& old_policy, 722 const Policy& new_policy, 723 bool should_update_priority) const; 724 725 void PauseRendererImpl(); 726 void ResumeRendererImpl(); 727 728 void NotifyVirtualTimePaused(); 729 void SetVirtualTimeStopped(bool virtual_time_stopped); 730 void ApplyVirtualTimePolicy(); 731 732 // Pauses the timer queues by inserting a fence that blocks any tasks posted 733 // after this point from running. Orthogonal to PauseTimerQueue. Care must 734 // be taken when using this API to avoid fighting with the TaskQueueThrottler. 735 void VirtualTimePaused(); 736 737 // Removes the fence added by VirtualTimePaused allowing timers to execute 738 // normally. Care must be taken when using this API to avoid fighting with the 739 // TaskQueueThrottler. 740 void VirtualTimeResumed(); 741 742 // Returns true if there is a change in the main thread's policy that should 743 // trigger a priority update. 744 bool ShouldUpdateTaskQueuePriorities(Policy new_policy) const; 745 746 // Computes compositor priority based on various experiments and 747 // the use case. Defaults to kNormalPriority. 748 TaskQueue::QueuePriority ComputeCompositorPriority() const; 749 750 // Used to update the compositor priority on the main thread. 751 void UpdateCompositorTaskQueuePriority(); 752 753 // Computes the priority for compositing based on the current use case. 754 // Returns nullopt if the use case does not need to set the priority. 755 base::Optional<TaskQueue::QueuePriority> 756 ComputeCompositorPriorityFromUseCase() const; 757 758 static void RunIdleTask(Thread::IdleTask, base::TimeTicks deadline); 759 760 // Probabilistically record all task metadata for the current task. 761 // If task belongs to a per-frame queue, this task is attributed to 762 // a particular Page, otherwise it's attributed to all Pages in the process. 763 void RecordTaskUkm( 764 MainThreadTaskQueue* queue, 765 const base::sequence_manager::Task& task, 766 const base::sequence_manager::TaskQueue::TaskTiming& task_timing); 767 768 UkmRecordingStatus RecordTaskUkmImpl( 769 MainThreadTaskQueue* queue, 770 const base::sequence_manager::Task& task, 771 const base::sequence_manager::TaskQueue::TaskTiming& task_timing, 772 FrameSchedulerImpl* frame_scheduler, 773 bool precise_attribution); 774 775 void SetNumberOfCompositingTasksToPrioritize(int number_of_tasks); 776 777 void ShutdownAllQueues(); 778 779 // Dispatch the callbacks which requested to be executed after the current 780 // task. 781 void DispatchOnTaskCompletionCallbacks(); 782 783 void AsValueIntoLocked(base::trace_event::TracedValue*, 784 base::TimeTicks optional_now) const; 785 786 bool AllPagesFrozen() const; 787 788 // Indicates that scheduler has been shutdown. 789 // It should be accessed only on the main thread, but couldn't be a member 790 // of MainThreadOnly struct because last might be destructed before we 791 // have to check this flag during scheduler's destruction. 792 bool was_shutdown_ = false; 793 794 bool has_ipc_callback_set_ = false; 795 bool IsIpcTrackingEnabledForAllPages(); 796 797 // This controller should be initialized before any TraceableVariables 798 // because they require one to initialize themselves. 799 TraceableVariableController tracing_controller_; 800 801 // Used for experiments on finch. On main thread instantiation, we cache 802 // the values of base::Feature flags using this struct, since calling 803 // base::Feature::IsEnabled is a relatively expensive operation. 804 // 805 // Note that it is important to keep this as the first member to ensure it is 806 // initialized first and can be used everywhere. 807 const SchedulingSettings scheduling_settings_; 808 809 std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager_; 810 MainThreadSchedulerHelper helper_; 811 scoped_refptr<MainThreadTaskQueue> idle_helper_queue_; 812 IdleHelper idle_helper_; 813 std::unique_ptr<TaskQueueThrottler> task_queue_throttler_; 814 RenderWidgetSignals render_widget_scheduler_signals_; 815 816 std::unique_ptr<FindInPageBudgetPoolController> 817 find_in_page_budget_pool_controller_; 818 819 const scoped_refptr<MainThreadTaskQueue> control_task_queue_; 820 const scoped_refptr<MainThreadTaskQueue> compositor_task_queue_; 821 scoped_refptr<MainThreadTaskQueue> virtual_time_control_task_queue_; 822 scoped_refptr<MainThreadTaskQueue> 823 back_forward_cache_ipc_tracking_task_queue_; 824 std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter> 825 compositor_task_queue_enabled_voter_; 826 827 using TaskQueueVoterMap = std::map< 828 scoped_refptr<MainThreadTaskQueue>, 829 std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter>>; 830 831 TaskQueueVoterMap task_runners_; 832 833 scoped_refptr<MainThreadTaskQueue> v8_task_queue_; 834 scoped_refptr<MainThreadTaskQueue> memory_purge_task_queue_; 835 scoped_refptr<MainThreadTaskQueue> non_waking_task_queue_; 836 837 scoped_refptr<base::SingleThreadTaskRunner> v8_task_runner_; 838 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; 839 scoped_refptr<base::SingleThreadTaskRunner> control_task_runner_; 840 scoped_refptr<base::SingleThreadTaskRunner> non_waking_task_runner_; 841 scoped_refptr<base::SingleThreadTaskRunner> 842 back_forward_cache_ipc_tracking_task_runner_; 843 844 MemoryPurgeManager memory_purge_manager_; 845 846 // Note |virtual_time_domain_| is lazily created. 847 std::unique_ptr<AutoAdvancingVirtualTimeDomain> virtual_time_domain_; 848 NonWakingTimeDomain non_waking_time_domain_; 849 850 base::RepeatingClosure update_policy_closure_; 851 DeadlineTaskRunner delayed_update_policy_runner_; 852 CancelableClosureHolder end_renderer_hidden_idle_period_closure_; 853 base::RepeatingClosure notify_agent_strategy_on_input_event_closure_; 854 base::RepeatingCallback<void(base::WeakPtr<const FrameSchedulerImpl>)> 855 agent_strategy_delay_callback_; 856 857 std::unique_ptr<AgentSchedulingStrategy> agent_scheduling_strategy_ = 858 AgentSchedulingStrategy::Create(*this); 859 860 // We have decided to improve thread safety at the cost of some boilerplate 861 // (the accessors) for the following data members. 862 struct MainThreadOnly { 863 MainThreadOnly( 864 MainThreadSchedulerImpl* main_thread_scheduler_impl, 865 const scoped_refptr<MainThreadTaskQueue>& compositor_task_runner, 866 const base::TickClock* time_source, 867 base::TimeTicks now); 868 ~MainThreadOnly(); 869 870 IdleTimeEstimator idle_time_estimator; 871 TraceableState<UseCase, TracingCategoryName::kDefault> current_use_case; 872 Policy current_policy; 873 base::TimeTicks current_policy_expiration_time; 874 base::TimeTicks estimated_next_frame_begin; 875 base::TimeTicks current_task_start_time; 876 base::TimeDelta compositor_frame_interval; 877 TraceableCounter<base::TimeDelta, TracingCategoryName::kDebug> 878 longest_jank_free_task_duration; 879 TraceableCounter<int, TracingCategoryName::kInfo> 880 renderer_pause_count; // Renderer is paused if non-zero. 881 882 TraceableObjectState<RAILMode, 883 TracingCategoryName::kTopLevel> 884 rail_mode_for_tracing; // Don't use except for tracing. 885 886 TraceableState<bool, TracingCategoryName::kTopLevel> renderer_hidden; 887 base::Optional<base::ScopedSampleMetadata> renderer_hidden_metadata; 888 TraceableState<bool, TracingCategoryName::kTopLevel> renderer_backgrounded; 889 TraceableState<bool, TracingCategoryName::kDefault> 890 keep_active_fetch_or_worker; 891 TraceableState<bool, TracingCategoryName::kDefault> 892 blocking_input_expected_soon; 893 TraceableState<bool, TracingCategoryName::kDebug> 894 have_reported_blocking_intervention_in_current_policy; 895 TraceableState<bool, TracingCategoryName::kDebug> 896 have_reported_blocking_intervention_since_navigation; 897 TraceableState<bool, TracingCategoryName::kDebug> 898 has_visible_render_widget_with_touch_handler; 899 TraceableState<bool, TracingCategoryName::kDebug> 900 in_idle_period_for_testing; 901 TraceableState<bool, TracingCategoryName::kInfo> use_virtual_time; 902 TraceableState<bool, TracingCategoryName::kTopLevel> is_audio_playing; 903 TraceableState<bool, TracingCategoryName::kDebug> 904 compositor_will_send_main_frame_not_expected; 905 TraceableState<bool, TracingCategoryName::kDebug> has_navigated; 906 TraceableState<bool, TracingCategoryName::kDebug> pause_timers_for_webview; 907 base::TimeTicks background_status_changed_at; 908 HashSet<PageSchedulerImpl*> page_schedulers; // Not owned. 909 base::ObserverList<RAILModeObserver>::Unchecked 910 rail_mode_observers; // Not owned. 911 MainThreadMetricsHelper metrics_helper; 912 TraceableState<WebRendererProcessType, TracingCategoryName::kTopLevel> 913 process_type; 914 TraceableState<base::Optional<TaskDescriptionForTracing>, 915 TracingCategoryName::kInfo> 916 task_description_for_tracing; // Don't use except for tracing. 917 TraceableState< 918 base::Optional<base::sequence_manager::TaskQueue::QueuePriority>, 919 TracingCategoryName::kInfo> 920 task_priority_for_tracing; // Only used for tracing. 921 base::Time initial_virtual_time; 922 base::TimeTicks initial_virtual_time_ticks; 923 924 // This is used for cross origin navigations to account for virtual time 925 // advancing in the previous renderer. 926 base::TimeDelta initial_virtual_time_offset; 927 VirtualTimePolicy virtual_time_policy; 928 929 // In VirtualTimePolicy::kDeterministicLoading virtual time is only allowed 930 // to advance if this is zero. 931 int virtual_time_pause_count; 932 933 // The maximum number amount of delayed task starvation we will allow in 934 // VirtualTimePolicy::kAdvance or VirtualTimePolicy::kDeterministicLoading 935 // unless the run_loop is nested (in which case infinite starvation is 936 // allowed). NB a value of 0 allows infinite starvation. 937 int max_virtual_time_task_starvation_count; 938 bool virtual_time_stopped; 939 940 // Holds task queues that are currently running. 941 // The queue for the inmost task is at the top of stack when there are 942 // nested RunLoops. 943 std::stack<scoped_refptr<MainThreadTaskQueue>, 944 std::vector<scoped_refptr<MainThreadTaskQueue>>> 945 running_queues; 946 947 // True if a nested RunLoop is running. 948 bool nested_runloop; 949 950 // High-priority for compositing events after input. This will cause 951 // compositing events get a higher priority until the start of the next 952 // animation frame. 953 TraceableState<bool, TracingCategoryName::kDefault> 954 prioritize_compositing_after_input; 955 956 // List of callbacks to execute after the current task. 957 WTF::Vector<base::OnceClosure> on_task_completion_callbacks; 958 959 // Compositing priority experiments (crbug.com/966177). 960 CompositorPriorityExperiments compositor_priority_experiments; 961 962 bool main_thread_compositing_is_fast; 963 964 // Priority given to the main thread's compositor task queue. Defaults to 965 // kNormalPriority and is updated via UpdateCompositorTaskQueuePriority(). 966 TraceableState<TaskQueue::QueuePriority, TracingCategoryName::kDefault> 967 compositor_priority; 968 }; 969 970 struct AnyThread { 971 explicit AnyThread(MainThreadSchedulerImpl* main_thread_scheduler_impl); 972 ~AnyThread(); 973 974 PendingUserInput::Monitor pending_input_monitor; 975 base::TimeTicks last_idle_period_end_time; 976 base::TimeTicks fling_compositor_escalation_deadline; 977 UserModel user_model; 978 TraceableState<bool, TracingCategoryName::kInfo> 979 awaiting_touch_start_response; 980 TraceableState<bool, TracingCategoryName::kInfo> in_idle_period; 981 TraceableState<bool, TracingCategoryName::kInfo> 982 begin_main_frame_on_critical_path; 983 TraceableState<bool, TracingCategoryName::kInfo> 984 last_gesture_was_compositor_driven; 985 TraceableState<bool, TracingCategoryName::kInfo> default_gesture_prevented; 986 TraceableState<bool, TracingCategoryName::kInfo> 987 have_seen_a_blocking_gesture; 988 TraceableState<bool, TracingCategoryName::kInfo> 989 waiting_for_any_main_frame_contentful_paint; 990 TraceableState<bool, TracingCategoryName::kInfo> 991 waiting_for_any_main_frame_meaningful_paint; 992 TraceableState<bool, TracingCategoryName::kInfo> 993 have_seen_input_since_navigation; 994 TraceableCounter<uint32_t, TracingCategoryName::kInfo> 995 begin_main_frame_scheduled_count; 996 }; 997 998 struct CompositorThreadOnly { 999 CompositorThreadOnly(); 1000 ~CompositorThreadOnly(); 1001 1002 WebInputEvent::Type last_input_type; 1003 std::unique_ptr<base::ThreadChecker> compositor_thread_checker; 1004 CheckOnValidThreadCompositorThreadOnly1005 void CheckOnValidThread() { 1006 #if DCHECK_IS_ON() 1007 // We don't actually care which thread this called from, just so long as 1008 // its consistent. 1009 if (!compositor_thread_checker) 1010 compositor_thread_checker.reset(new base::ThreadChecker()); 1011 DCHECK(compositor_thread_checker->CalledOnValidThread()); 1012 #endif 1013 } 1014 }; 1015 1016 // Don't access main_thread_only_, instead use main_thread_only(). 1017 MainThreadOnly main_thread_only_; main_thread_only()1018 MainThreadOnly& main_thread_only() { 1019 helper_.CheckOnValidThread(); 1020 return main_thread_only_; 1021 } main_thread_only()1022 const struct MainThreadOnly& main_thread_only() const { 1023 helper_.CheckOnValidThread(); 1024 return main_thread_only_; 1025 } 1026 1027 mutable base::Lock any_thread_lock_; 1028 // Don't access any_thread_, instead use any_thread(). 1029 AnyThread any_thread_; any_thread()1030 AnyThread& any_thread() { 1031 any_thread_lock_.AssertAcquired(); 1032 return any_thread_; 1033 } any_thread()1034 const struct AnyThread& any_thread() const { 1035 any_thread_lock_.AssertAcquired(); 1036 return any_thread_; 1037 } 1038 1039 // Don't access compositor_thread_only_, instead use CompositorThreadOnly(). 1040 CompositorThreadOnly compositor_thread_only_; GetCompositorThreadOnly()1041 CompositorThreadOnly& GetCompositorThreadOnly() { 1042 compositor_thread_only_.CheckOnValidThread(); 1043 return compositor_thread_only_; 1044 } 1045 1046 PollableThreadSafeFlag policy_may_need_update_; 1047 PollableThreadSafeFlag notify_agent_strategy_task_posted_; 1048 WTF::HashSet<AgentGroupSchedulerImpl*> agent_group_schedulers_; 1049 WebAgentGroupScheduler* current_agent_group_scheduler_{nullptr}; 1050 1051 base::WeakPtrFactory<MainThreadSchedulerImpl> weak_factory_{this}; 1052 1053 DISALLOW_COPY_AND_ASSIGN(MainThreadSchedulerImpl); 1054 }; 1055 1056 } // namespace scheduler 1057 } // namespace blink 1058 1059 #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_SCHEDULER_IMPL_H_ 1060