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