1# What is this 2This file documents high level parts of the sequence manager. 3 4The sequence manager provides a set of prioritized FIFO task queues, which 5allows funneling multiple sequences of immediate and delayed tasks on a single 6underlying sequence. 7 8## Work Queue and Task selection 9Both immediate tasks and delayed tasks are posted to a `TaskQueue` via an 10associated `TaskRunner`. `TaskQueue`s use distinct primitive FIFO queues, called 11`WorkQueue`s, to manage immediate tasks and delayed tasks. Tasks eventually end 12up in their assigned `WorkQueue` which is made directly visible to 13`SequenceManager` through `TaskQueueSelector`. 14`SequenceManagerImpl::SelectNextTask()` uses 15`TaskQueueSelector::SelectWorkQueueToService()` to select the next work queue 16based on various policy e.g. priority, from which 1 task is popped at a time. 17 18## Journey of a Task 19Task queues have a mechanism to allow efficient cross-thread posting with the 20use of 2 work queues, `immediate_incoming_queue` which is used when posting, and 21`immediate_work_queue` used to pop tasks from. An immediate task posted from the 22main thread is pushed on `immediate_incoming_queue` in 23`TaskQueueImpl::PostImmediateTaskImpl()`. If the work queue was empty, 24`SequenceManager` is notified and the `TaskQueue` is registered to do 25`ReloadEmptyImmediateWorkQueue()` before SequenceManager selects a task, which 26moves tasks from `immediate_incoming_queue` to `immediate_work_queue` in batch 27for all registered `TaskQueue`s. The tasks then follow the regular work queue 28selection mechanism. 29 30## Journey of a WakeUp 31A `WakeUp` represents a time at which a delayed task wants to run. 32 33Each `TaskQueueImpl` maintains its own next wake-up as 34`main_thread_only().scheduled_wake_up`, associated with the earliest pending 35delayed task. It communicates its wake up to the WakeUpQueue via 36`WakeUpQueue::SetNextWakeUpForQueue()`. The `WakeUpQueue` is responsible for 37determining the single next wake up time for the thread. This is accessed from 38`SequenceManagerImpl` and may determine the next run time if there's no 39immediate work, which ultimately gets passed to the MessagePump, typically via 40`MessagePump::Delegate::NextWorkInfo` (returned by 41`ThreadControllerWithMessagePumpImpl::DoWork()`) or by 42`MessagePump::ScheduleDelayedWork()` (on rare occasions where the next WakeUp is 43scheduled on the main thread from outside a `DoWork()`). When a delayed run time 44associated with a wake-up is reached, `WakeUpQueue` is notified through 45`WakeUpQueue::MoveReadyDelayedTasksToWorkQueues()` and in turn notifies all 46`TaskQueue`s whose wake-up can be resolved. This lets each `TaskQueue`s process 47ripe delayed tasks. 48 49## Journey of a delayed Task 50A delayed Task posted cross-thread generates an immediate Task to run 51`TaskQueueImpl::ScheduleDelayedWorkTask()` which eventually calls 52`TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread()`, so that it can be 53enqueued on the main thread. A delayed Task posted from the main thread skips 54this step and calls 55`TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread()` directly. The Task 56is then pushed on `main_thread_only().delayed_incoming_queue` and possibly 57updates the next task queue wake-up. Once the delayed run time is reached, 58possibly because the wake-up is resolved, the delayed task is moved to 59`main_thread_only().delayed_work_queue` and follows the regular work queue 60selection mechanism. 61 62## TimeDomain and TickClock 63`SequenceManager` and related classes use a common `TickClock` that can be 64injected by specifying a `TimeDomain`. A `TimeDomain` is a specialisation of 65`TickClock` that gets notified when the `MessagePump` is about to go idle via 66TimeDomain::MaybeFastForwardToWakeUp(), and can use the signal to fast forward 67in time. This is used in `TaskEnvironment` to support `MOCK_TIME`, and in 68devtools to support virtual time. 69