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