1 // Copyright 2018 The Chromium Authors 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 BASE_TASK_SEQUENCE_MANAGER_TASK_QUEUE_IMPL_H_ 6 #define BASE_TASK_SEQUENCE_MANAGER_TASK_QUEUE_IMPL_H_ 7 8 #include <stddef.h> 9 10 #include <functional> 11 #include <memory> 12 #include <optional> 13 #include <queue> 14 #include <set> 15 #include <utility> 16 #include <vector> 17 18 #include "base/base_export.h" 19 #include "base/containers/flat_map.h" 20 #include "base/containers/intrusive_heap.h" 21 #include "base/dcheck_is_on.h" 22 #include "base/functional/callback.h" 23 #include "base/memory/raw_ptr.h" 24 #include "base/memory/scoped_refptr.h" 25 #include "base/memory/weak_ptr.h" 26 #include "base/observer_list.h" 27 #include "base/pending_task.h" 28 #include "base/task/common/checked_lock.h" 29 #include "base/task/common/operations_controller.h" 30 #include "base/task/sequence_manager/associated_thread_id.h" 31 #include "base/task/sequence_manager/atomic_flag_set.h" 32 #include "base/task/sequence_manager/enqueue_order.h" 33 #include "base/task/sequence_manager/fence.h" 34 #include "base/task/sequence_manager/lazily_deallocated_deque.h" 35 #include "base/task/sequence_manager/sequenced_task_source.h" 36 #include "base/task/sequence_manager/task_queue.h" 37 #include "base/task/sequence_manager/tasks.h" 38 #include "base/threading/thread_checker.h" 39 #include "base/time/time_override.h" 40 #include "base/trace_event/base_tracing_forward.h" 41 #include "base/values.h" 42 43 namespace base { 44 class LazyNow; 45 namespace sequence_manager::internal { 46 47 class SequenceManagerImpl; 48 class WorkQueue; 49 class WorkQueueSets; 50 class WakeUpQueue; 51 52 // TaskQueueImpl has four main queues: 53 // 54 // Immediate (non-delayed) tasks: 55 // |immediate_incoming_queue| - PostTask enqueues tasks here. 56 // |immediate_work_queue| - SequenceManager takes immediate tasks here. 57 // 58 // Delayed tasks 59 // |delayed_incoming_queue| - PostDelayedTask enqueues tasks here. 60 // |delayed_work_queue| - SequenceManager takes delayed tasks here. 61 // 62 // The |immediate_incoming_queue| can be accessed from any thread, the other 63 // queues are main-thread only. To reduce the overhead of locking, 64 // |immediate_work_queue| is swapped with |immediate_incoming_queue| when 65 // |immediate_work_queue| becomes empty. 66 // 67 // Delayed tasks are initially posted to |delayed_incoming_queue| and a wake-up 68 // is scheduled with the TimeDomain. When the delay has elapsed, the TimeDomain 69 // calls UpdateDelayedWorkQueue and ready delayed tasks are moved into the 70 // |delayed_work_queue|. Note the EnqueueOrder (used for ordering) for a delayed 71 // task is not set until it's moved into the |delayed_work_queue|. 72 // 73 // TaskQueueImpl uses the WorkQueueSets and the TaskQueueSelector to implement 74 // prioritization. Task selection is done by the TaskQueueSelector and when a 75 // queue is selected, it round-robins between the |immediate_work_queue| and 76 // |delayed_work_queue|. The reason for this is we want to make sure delayed 77 // tasks (normally the most common type) don't starve out immediate work. 78 class BASE_EXPORT TaskQueueImpl : public TaskQueue { 79 public: 80 // Initializes the state of all the task queue features. Must be invoked 81 // after FeatureList initialization and while Chrome is still single-threaded. 82 static void InitializeFeatures(); 83 84 TaskQueueImpl(SequenceManagerImpl* sequence_manager, 85 WakeUpQueue* wake_up_queue, 86 const TaskQueue::Spec& spec); 87 88 TaskQueueImpl(const TaskQueueImpl&) = delete; 89 TaskQueueImpl& operator=(const TaskQueueImpl&) = delete; 90 ~TaskQueueImpl() override; 91 92 // Types of queues TaskQueueImpl is maintaining internally. 93 enum class WorkQueueType { kImmediate, kDelayed }; 94 95 // Some methods have fast paths when on the main thread. 96 enum class CurrentThread { kMainThread, kNotMainThread }; 97 98 // Non-nestable tasks may get deferred but such queue is being maintained on 99 // SequenceManager side, so we need to keep information how to requeue it. 100 struct DeferredNonNestableTask { 101 Task task; 102 103 // `task_queue` is not a raw_ptr<...> for performance reasons (based on 104 // analysis of sampling profiler data and tab_search:top100:2020). 105 RAW_PTR_EXCLUSION internal::TaskQueueImpl* task_queue; 106 107 WorkQueueType work_queue_type; 108 }; 109 110 using OnNextWakeUpChangedCallback = RepeatingCallback<void(TimeTicks)>; 111 using OnTaskStartedHandler = 112 RepeatingCallback<void(const Task&, const TaskQueue::TaskTiming&)>; 113 using OnTaskCompletedHandler = 114 RepeatingCallback<void(const Task&, TaskQueue::TaskTiming*, LazyNow*)>; 115 using OnTaskPostedHandler = RepeatingCallback<void(const Task&)>; 116 using TaskExecutionTraceLogger = 117 RepeatingCallback<void(perfetto::EventContext&, const Task&)>; 118 119 // TaskQueue implementation. 120 const char* GetName() const override; 121 bool IsQueueEnabled() const override; 122 bool IsEmpty() const override; 123 size_t GetNumberOfPendingTasks() const override; 124 bool HasTaskToRunImmediatelyOrReadyDelayedTask() const override; 125 std::optional<WakeUp> GetNextDesiredWakeUp() override; 126 void SetQueuePriority(TaskQueue::QueuePriority priority) override; 127 TaskQueue::QueuePriority GetQueuePriority() const override; 128 void AddTaskObserver(TaskObserver* task_observer) override; 129 void RemoveTaskObserver(TaskObserver* task_observer) override; 130 void InsertFence(TaskQueue::InsertFencePosition position) override; 131 void InsertFenceAt(TimeTicks time) override; 132 void RemoveFence() override; 133 bool HasActiveFence() override; 134 bool BlockedByFence() const override; 135 void SetThrottler(TaskQueue::Throttler* throttler) override; 136 void ResetThrottler() override; 137 void UpdateWakeUp(LazyNow* lazy_now) override; 138 void SetShouldReportPostedTasksWhenDisabled(bool should_report) override; 139 scoped_refptr<SingleThreadTaskRunner> CreateTaskRunner( 140 TaskType task_type) const override; 141 const scoped_refptr<SingleThreadTaskRunner>& task_runner() const override; 142 void SetOnTaskStartedHandler(OnTaskStartedHandler handler) override; 143 void SetOnTaskCompletedHandler(OnTaskCompletedHandler handler) override; 144 [[nodiscard]] std::unique_ptr<TaskQueue::OnTaskPostedCallbackHandle> 145 AddOnTaskPostedHandler(OnTaskPostedHandler handler) override; 146 void SetTaskExecutionTraceLogger(TaskExecutionTraceLogger logger) override; 147 std::unique_ptr<QueueEnabledVoter> CreateQueueEnabledVoter() override; 148 149 void SetQueueEnabled(bool enabled); 150 void UnregisterTaskQueue(); 151 152 QueueName GetProtoName() const; 153 154 // Returns true if a (potentially hypothetical) task with the specified 155 // |enqueue_order| could run on the queue. Must be called from the main 156 // thread. 157 bool CouldTaskRun(EnqueueOrder enqueue_order) const; 158 159 // Returns true if a task with |enqueue_order| obtained from this queue was 160 // ever in the queue while it was disabled, blocked by a fence, or less 161 // important than kNormalPriority. 162 bool WasBlockedOrLowPriority(EnqueueOrder enqueue_order) const; 163 164 // Must only be called from the thread this task queue was created on. 165 void ReloadEmptyImmediateWorkQueue(); 166 167 Value::Dict AsValue(TimeTicks now, bool force_verbose) const; 168 GetQuiescenceMonitored()169 bool GetQuiescenceMonitored() const { return should_monitor_quiescence_; } GetShouldNotifyObservers()170 bool GetShouldNotifyObservers() const { return should_notify_observers_; } 171 172 void NotifyWillProcessTask(const Task& task, 173 bool was_blocked_or_low_priority); 174 void NotifyDidProcessTask(const Task& task); 175 176 // Returns true iff this queue has work that can execute now, i.e. immediate 177 // tasks or delayed tasks that have been transferred to the work queue by 178 // MoveReadyDelayedTasksToWorkQueue(). Delayed tasks that are still in the 179 // incoming queue are not taken into account. Ignores the queue's enabled 180 // state and fences. 181 bool HasTaskToRunImmediately() const; 182 bool HasTaskToRunImmediatelyLocked() const 183 EXCLUSIVE_LOCKS_REQUIRED(any_thread_lock_); 184 has_pending_high_resolution_tasks()185 bool has_pending_high_resolution_tasks() const { 186 return main_thread_only() 187 .delayed_incoming_queue.has_pending_high_resolution_tasks(); 188 } 189 delayed_work_queue()190 WorkQueue* delayed_work_queue() { 191 return main_thread_only().delayed_work_queue.get(); 192 } 193 delayed_work_queue()194 const WorkQueue* delayed_work_queue() const { 195 return main_thread_only().delayed_work_queue.get(); 196 } 197 immediate_work_queue()198 WorkQueue* immediate_work_queue() { 199 return main_thread_only().immediate_work_queue.get(); 200 } 201 immediate_work_queue()202 const WorkQueue* immediate_work_queue() const { 203 return main_thread_only().immediate_work_queue.get(); 204 } 205 task_execution_trace_logger()206 TaskExecutionTraceLogger task_execution_trace_logger() const { 207 return main_thread_only().task_execution_trace_logger; 208 } 209 210 // Removes all canceled tasks from the front of the delayed incoming queue. 211 // After calling this, GetNextDesiredWakeUp() is guaranteed to return a time 212 // for a non-canceled task, if one exists. Return true if a canceled task was 213 // removed. 214 bool RemoveAllCanceledDelayedTasksFromFront(LazyNow* lazy_now); 215 216 // Enqueues in `delayed_work_queue` all delayed tasks which must run now 217 // (cannot be postponed) and possibly some delayed tasks which can run now but 218 // could be postponed (due to how tasks are stored, it is not possible to 219 // retrieve all such tasks efficiently). Must be called from the main thread. 220 void MoveReadyDelayedTasksToWorkQueue(LazyNow* lazy_now, 221 EnqueueOrder enqueue_order); 222 223 void OnWakeUp(LazyNow* lazy_now, EnqueueOrder enqueue_order); 224 wake_up_queue()225 const WakeUpQueue* wake_up_queue() const { 226 return main_thread_only().wake_up_queue; 227 } 228 heap_handle()229 HeapHandle heap_handle() const { return main_thread_only().heap_handle; } 230 set_heap_handle(HeapHandle heap_handle)231 void set_heap_handle(HeapHandle heap_handle) { 232 main_thread_only().heap_handle = heap_handle; 233 } 234 235 // Pushes |task| onto the front of the specified work queue. Caution must be 236 // taken with this API because you could easily starve out other work. 237 // TODO(kraynov): Simplify non-nestable task logic https://crbug.com/845437. 238 void RequeueDeferredNonNestableTask(DeferredNonNestableTask task); 239 240 void PushImmediateIncomingTaskForTest(Task task); 241 242 // Iterates over |delayed_incoming_queue| removing canceled tasks. In 243 // addition MaybeShrinkQueue is called on all internal queues. 244 void ReclaimMemory(TimeTicks now); 245 246 void OnTaskStarted(const Task& task, 247 const TaskQueue::TaskTiming& task_timing); 248 void OnTaskCompleted(const Task& task, 249 TaskQueue::TaskTiming* task_timing, 250 LazyNow* lazy_now); 251 bool RequiresTaskTiming() const; 252 253 WeakPtr<SequenceManagerImpl> GetSequenceManagerWeakPtr(); 254 sequence_manager()255 SequenceManagerImpl* sequence_manager() const { return sequence_manager_; } 256 257 // Returns true if this queue is unregistered or task queue manager is deleted 258 // and this queue can be safely deleted on any thread. 259 bool IsUnregistered() const; 260 261 // Called by the associated sequence manager when it becomes bound. Updates 262 // the weak pointer stored in voters with one bound to the correct thread. 263 void CompleteInitializationOnBoundThread(); 264 265 void AddQueueEnabledVoter(bool voter_is_enabled, 266 TaskQueue::QueueEnabledVoter& voter); 267 void RemoveQueueEnabledVoter(bool voter_is_enabled, 268 TaskQueue::QueueEnabledVoter& voter); 269 void OnQueueEnabledVoteChanged(bool enabled); 270 271 protected: 272 // Sets this queue's next wake up time to |wake_up| in the time domain. 273 void SetNextWakeUp(LazyNow* lazy_now, std::optional<WakeUp> wake_up); 274 275 private: 276 friend class WorkQueue; 277 friend class WorkQueueTest; 278 friend class DelayedTaskHandleDelegate; 279 280 // A TaskQueueImpl instance can be destroyed or unregistered before all its 281 // associated TaskRunner instances are (they are refcounted). Thus we need a 282 // way to prevent TaskRunner instances from posting further tasks. This class 283 // guards PostTask calls using an OperationsController. 284 // This class is ref-counted as both the TaskQueueImpl instance and all 285 // associated TaskRunner instances share the same GuardedTaskPoster instance. 286 // When TaskQueueImpl shuts down it calls ShutdownAndWaitForZeroOperations(), 287 // preventing further PostTask calls being made to the underlying 288 // TaskQueueImpl. 289 class GuardedTaskPoster : public RefCountedThreadSafe<GuardedTaskPoster> { 290 public: 291 explicit GuardedTaskPoster(TaskQueueImpl* outer); 292 293 bool PostTask(PostedTask task); 294 DelayedTaskHandle PostCancelableTask(PostedTask task); 295 bool RunOrPostTask(PostedTask task); 296 StartAcceptingOperations()297 void StartAcceptingOperations() { 298 operations_controller_.StartAcceptingOperations(); 299 } 300 ShutdownAndWaitForZeroOperations()301 void ShutdownAndWaitForZeroOperations() { 302 operations_controller_.ShutdownAndWaitForZeroOperations(); 303 // `operations_controller_` won't let any more operations here, and 304 // `outer_` might get destroyed before `this` does, so clearing `outer_` 305 // avoids a potential dangling pointer. 306 outer_ = nullptr; 307 } 308 309 private: 310 friend class RefCountedThreadSafe<GuardedTaskPoster>; 311 312 ~GuardedTaskPoster(); 313 314 base::internal::OperationsController operations_controller_; 315 // Pointer might be stale, access guarded by |operations_controller_| 316 raw_ptr<TaskQueueImpl> outer_; 317 }; 318 319 class TaskRunner final : public SingleThreadTaskRunner { 320 public: 321 explicit TaskRunner( 322 scoped_refptr<GuardedTaskPoster> task_poster, 323 scoped_refptr<const AssociatedThreadId> associated_thread, 324 TaskType task_type); 325 326 bool PostDelayedTask(const Location& location, 327 OnceClosure callback, 328 TimeDelta delay) final; 329 bool PostDelayedTaskAt(subtle::PostDelayedTaskPassKey, 330 const Location& location, 331 OnceClosure callback, 332 TimeTicks delayed_run_time, 333 base::subtle::DelayPolicy delay_policy) final; 334 DelayedTaskHandle PostCancelableDelayedTaskAt( 335 subtle::PostDelayedTaskPassKey, 336 const Location& location, 337 OnceClosure callback, 338 TimeTicks delayed_run_time, 339 base::subtle::DelayPolicy delay_policy) final; 340 DelayedTaskHandle PostCancelableDelayedTask(subtle::PostDelayedTaskPassKey, 341 const Location& location, 342 OnceClosure callback, 343 TimeDelta delay) final; 344 bool PostNonNestableDelayedTask(const Location& location, 345 OnceClosure callback, 346 TimeDelta delay) final; 347 bool RunOrPostTask(subtle::RunOrPostTaskPassKey, 348 const Location& from_here, 349 OnceClosure task) final; 350 bool BelongsToCurrentThread() const final; 351 bool RunsTasksInCurrentSequence() const final; 352 353 private: 354 ~TaskRunner() final; 355 356 const scoped_refptr<GuardedTaskPoster> task_poster_; 357 const scoped_refptr<const AssociatedThreadId> associated_thread_; 358 const TaskType task_type_; 359 }; 360 361 class OnTaskPostedCallbackHandleImpl 362 : public TaskQueue::OnTaskPostedCallbackHandle { 363 public: 364 OnTaskPostedCallbackHandleImpl( 365 TaskQueueImpl* task_queue_impl, 366 scoped_refptr<const AssociatedThreadId> associated_thread_); 367 ~OnTaskPostedCallbackHandleImpl() override; 368 369 // Callback handles can outlive the associated TaskQueueImpl, so the 370 // reference needs to be cleared when the queue is unregistered. UnregisterTaskQueue()371 void UnregisterTaskQueue() { task_queue_impl_ = nullptr; } 372 373 private: 374 raw_ptr<TaskQueueImpl> task_queue_impl_; 375 const scoped_refptr<const AssociatedThreadId> associated_thread_; 376 }; 377 378 // A queue for holding delayed tasks before their delay has expired. 379 struct DelayedIncomingQueue { 380 public: 381 DelayedIncomingQueue(); 382 DelayedIncomingQueue(const DelayedIncomingQueue&) = delete; 383 DelayedIncomingQueue& operator=(const DelayedIncomingQueue&) = delete; 384 ~DelayedIncomingQueue(); 385 386 void push(Task task); 387 void remove(HeapHandle heap_handle); 388 Task take_top(); emptyDelayedIncomingQueue389 bool empty() const { return queue_.empty(); } sizeDelayedIncomingQueue390 size_t size() const { return queue_.size(); } topDelayedIncomingQueue391 const Task& top() const { return queue_.top(); } 392 void swap(DelayedIncomingQueue* other); 393 has_pending_high_resolution_tasksDelayedIncomingQueue394 bool has_pending_high_resolution_tasks() const { 395 return pending_high_res_tasks_; 396 } 397 398 // TODO(crbug.com/1155905): we pass SequenceManager to be able to record 399 // crash keys. Remove this parameter after chasing down this crash. 400 void SweepCancelledTasks(SequenceManagerImpl* sequence_manager); 401 Value::List AsValue(TimeTicks now) const; 402 403 private: 404 struct Compare { 405 bool operator()(const Task& lhs, const Task& rhs) const; 406 }; 407 IntrusiveHeap<Task, Compare> queue_; 408 409 // Number of pending tasks in the queue that need high resolution timing. 410 int pending_high_res_tasks_ = 0; 411 }; 412 413 struct MainThreadOnly { 414 MainThreadOnly(TaskQueueImpl* task_queue, WakeUpQueue* wake_up_queue); 415 ~MainThreadOnly(); 416 417 raw_ptr<WakeUpQueue> wake_up_queue; 418 419 raw_ptr<TaskQueue::Throttler> throttler = nullptr; 420 421 std::unique_ptr<WorkQueue> delayed_work_queue; 422 std::unique_ptr<WorkQueue> immediate_work_queue; 423 DelayedIncomingQueue delayed_incoming_queue; 424 ObserverList<TaskObserver>::UncheckedAndDanglingUntriaged task_observers; 425 HeapHandle heap_handle; 426 bool is_enabled = true; 427 std::optional<Fence> current_fence; 428 std::optional<TimeTicks> delayed_fence; 429 // Snapshots the next sequence number when the queue is unblocked, otherwise 430 // it contains EnqueueOrder::none(). If the EnqueueOrder of a task just 431 // popped from this queue is greater than this, it means that the queue was 432 // never disabled or blocked by a fence while the task was queued. 433 EnqueueOrder enqueue_order_at_which_we_became_unblocked; 434 // If the EnqueueOrder of a task just popped from this queue is greater than 435 // this, it means that the queue was never disabled, blocked by a fence or 436 // less important than kNormalPriority while the task was queued. 437 // 438 // Implementation details: 439 // 1) When the queue is made less important than kNormalPriority, this is 440 // set to EnqueueOrder::max(). The EnqueueOrder of any task will compare 441 // less than this. 442 // 2) When the queue is made at least as important as kNormalPriority, this 443 // snapshots the next sequence number. If the queue is blocked, the value 444 // is irrelevant because no task should be popped. If the queue is not 445 // blocked, the EnqueueOrder of any already queued task will compare less 446 // than this. 447 // 3) When the queue is unblocked while at least as important as 448 // kNormalPriority, this snapshots the next sequence number. The 449 // EnqueueOrder of any already queued task will compare less than this. 450 // 451 // TODO(crbug.com/1249857): Change this to use `TaskOrder`. 452 EnqueueOrder 453 enqueue_order_at_which_we_became_unblocked_with_normal_priority; 454 OnTaskStartedHandler on_task_started_handler; 455 OnTaskCompletedHandler on_task_completed_handler; 456 TaskExecutionTraceLogger task_execution_trace_logger; 457 // Last reported wake up, used only in UpdateWakeUp to avoid 458 // excessive calls. 459 std::optional<WakeUp> scheduled_wake_up; 460 // If false, queue will be disabled. Used only for tests. 461 bool is_enabled_for_test = true; 462 // The time at which the task queue was disabled, if it is currently 463 // disabled. 464 std::optional<TimeTicks> disabled_time; 465 // Whether or not the task queue should emit tracing events for tasks 466 // posted to this queue when it is disabled. 467 bool should_report_posted_tasks_when_disabled = false; 468 469 int enabled_voter_count = 0; 470 int voter_count = 0; 471 }; 472 473 void PostTask(PostedTask task); 474 void RemoveCancelableTask(HeapHandle heap_handle); 475 476 void PostImmediateTaskImpl(PostedTask task, CurrentThread current_thread); 477 void PostDelayedTaskImpl(PostedTask task, CurrentThread current_thread); 478 479 // Push the task onto the |delayed_incoming_queue|. Lock-free main thread 480 // only fast path. 481 void PushOntoDelayedIncomingQueueFromMainThread(Task pending_task, 482 LazyNow* lazy_now, 483 bool notify_task_annotator); 484 485 // Push the task onto the |delayed_incoming_queue|. Slow path from other 486 // threads. 487 void PushOntoDelayedIncomingQueue(Task pending_task); 488 489 void ScheduleDelayedWorkTask(Task pending_task); 490 491 void MoveReadyImmediateTasksToImmediateWorkQueueLocked() 492 EXCLUSIVE_LOCKS_REQUIRED(any_thread_lock_); 493 494 // LazilyDeallocatedDeque use TimeTicks to figure out when to resize. We 495 // should use real time here always. 496 using TaskDeque = 497 LazilyDeallocatedDeque<Task, subtle::TimeTicksNowIgnoringOverride>; 498 499 // Extracts all the tasks from the immediate incoming queue and swaps it with 500 // |queue| which must be empty. 501 // Can be called from any thread. 502 void TakeImmediateIncomingQueueTasks(TaskDeque* queue); 503 504 void TraceQueueSize() const; 505 static Value::List QueueAsValue(const TaskDeque& queue, TimeTicks now); 506 static Value::Dict TaskAsValue(const Task& task, TimeTicks now); 507 508 // Returns a Task representation for `delayed_task`. 509 Task MakeDelayedTask(PostedTask delayed_task, LazyNow* lazy_now) const; 510 511 // Activate a delayed fence if a time has come based on `task`'s delayed run 512 // time. 513 void ActivateDelayedFenceIfNeeded(const Task& task); 514 515 // Updates state protected by any_thread_lock_. 516 void UpdateCrossThreadQueueStateLocked() 517 EXCLUSIVE_LOCKS_REQUIRED(any_thread_lock_); 518 519 TimeDelta GetTaskDelayAdjustment(CurrentThread current_thread); 520 521 // Reports the task if it was due to IPC and was posted to a disabled queue. 522 // This should be called after WillQueueTask has been called for the task. 523 void MaybeReportIpcTaskQueuedFromMainThread(const Task& pending_task); 524 bool ShouldReportIpcTaskQueuedFromAnyThreadLocked( 525 base::TimeDelta* time_since_disabled) 526 EXCLUSIVE_LOCKS_REQUIRED(any_thread_lock_); 527 void MaybeReportIpcTaskQueuedFromAnyThreadLocked(const Task& pending_task) 528 EXCLUSIVE_LOCKS_REQUIRED(any_thread_lock_); 529 void MaybeReportIpcTaskQueuedFromAnyThreadUnlocked(const Task& pending_task); 530 void ReportIpcTaskQueued(const Task& pending_task, 531 const base::TimeDelta& time_since_disabled); 532 533 // Invoked when the queue becomes enabled and not blocked by a fence. 534 void OnQueueUnblocked(); 535 536 void InsertFence(Fence fence); 537 538 void RemoveOnTaskPostedHandler( 539 OnTaskPostedCallbackHandleImpl* on_task_posted_callback_handle); 540 541 TaskQueue::QueuePriority DefaultPriority() const; 542 AreAllQueueEnabledVotersEnabled()543 bool AreAllQueueEnabledVotersEnabled() const { 544 return main_thread_only().enabled_voter_count == 545 main_thread_only().voter_count; 546 } 547 548 // Returns whether the queue is enabled. May be invoked from any thread. 549 bool IsQueueEnabledFromAnyThread() const; 550 551 QueueName name_; 552 const raw_ptr<SequenceManagerImpl, AcrossTasksDanglingUntriaged> 553 sequence_manager_; 554 555 const scoped_refptr<const AssociatedThreadId> associated_thread_; 556 557 const scoped_refptr<GuardedTaskPoster> task_poster_; 558 559 mutable base::internal::CheckedLock any_thread_lock_; 560 561 struct AnyThread { 562 // Mirrored from MainThreadOnly. These are only used for tracing. 563 struct TracingOnly { 564 TracingOnly(); 565 ~TracingOnly(); 566 567 std::optional<TimeTicks> disabled_time; 568 bool should_report_posted_tasks_when_disabled = false; 569 }; 570 571 AnyThread(); 572 ~AnyThread(); 573 574 TaskDeque immediate_incoming_queue; 575 576 bool immediate_work_queue_empty = true; 577 bool post_immediate_task_should_schedule_work = true; 578 bool unregistered = false; 579 bool is_enabled = true; 580 581 base::flat_map<raw_ptr<OnTaskPostedCallbackHandleImpl>, OnTaskPostedHandler> 582 on_task_posted_handlers; 583 584 #if DCHECK_IS_ON() 585 // A cache of |immediate_work_queue->work_queue_set_index()| which is used 586 // to index into 587 // SequenceManager::Settings::per_priority_cross_thread_task_delay to apply 588 // a priority specific delay for debugging purposes. 589 size_t queue_set_index = 0; 590 #endif 591 592 TracingOnly tracing_only; 593 }; 594 595 AnyThread any_thread_ GUARDED_BY(any_thread_lock_); 596 597 MainThreadOnly main_thread_only_; main_thread_only()598 MainThreadOnly& main_thread_only() { 599 DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker); 600 return main_thread_only_; 601 } main_thread_only()602 const MainThreadOnly& main_thread_only() const { 603 DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker); 604 return main_thread_only_; 605 } 606 607 // Handle to our entry within the SequenceManagers |empty_queues_to_reload_| 608 // atomic flag set. Used to signal that this queue needs to be reloaded. 609 // If you call SetActive(false) you should do so inside |any_thread_lock_| 610 // because there is a danger a cross thread PostTask might reset it before we 611 // make |immediate_work_queue| non-empty. 612 AtomicFlagSet::AtomicFlag empty_queues_to_reload_handle_; 613 614 const bool should_monitor_quiescence_; 615 const bool should_notify_observers_; 616 const bool delayed_fence_allowed_; 617 618 const scoped_refptr<SingleThreadTaskRunner> default_task_runner_; 619 620 base::WeakPtrFactory<TaskQueueImpl> voter_weak_ptr_factory_{this}; 621 }; 622 623 } // namespace sequence_manager::internal 624 } // namespace base 625 626 #endif // BASE_TASK_SEQUENCE_MANAGER_TASK_QUEUE_IMPL_H_ 627