tree: fb0c928cbe9cd22b03d01342d60d08c270e741bb [path history] [tgz]
  1. test/
  2. associated_thread_id.cc
  3. associated_thread_id.h
  4. atomic_flag_set.cc
  5. atomic_flag_set.h
  6. atomic_flag_set_unittest.cc
  7. delayed_task_handle_delegate.cc
  8. delayed_task_handle_delegate.h
  9. enqueue_order.h
  10. enqueue_order_generator.cc
  11. enqueue_order_generator.h
  12. fence.cc
  13. fence.h
  14. lazily_deallocated_deque.h
  15. lazily_deallocated_deque_unittest.cc
  16. README.md
  17. sequence_manager.cc
  18. sequence_manager.h
  19. sequence_manager_impl.cc
  20. sequence_manager_impl.h
  21. sequence_manager_impl_unittest.cc
  22. sequence_manager_perftest.cc
  23. sequenced_task_source.cc
  24. sequenced_task_source.h
  25. task_order.cc
  26. task_order.h
  27. task_order_unittest.cc
  28. task_queue.cc
  29. task_queue.h
  30. task_queue_impl.cc
  31. task_queue_impl.h
  32. task_queue_selector.cc
  33. task_queue_selector.h
  34. task_queue_selector_unittest.cc
  35. task_queue_unittest.cc
  36. task_time_observer.h
  37. tasks.cc
  38. tasks.h
  39. thread_controller.cc
  40. thread_controller.h
  41. thread_controller_impl.cc
  42. thread_controller_impl.h
  43. thread_controller_power_monitor.cc
  44. thread_controller_power_monitor.h
  45. thread_controller_power_monitor_unittest.cc
  46. thread_controller_with_message_pump_impl.cc
  47. thread_controller_with_message_pump_impl.h
  48. thread_controller_with_message_pump_impl_unittest.cc
  49. time_domain.cc
  50. time_domain.h
  51. wake_up_queue.cc
  52. wake_up_queue.h
  53. wake_up_queue_unittest.cc
  54. work_deduplicator.cc
  55. work_deduplicator.h
  56. work_deduplicator_unittest.cc
  57. work_queue.cc
  58. work_queue.h
  59. work_queue_sets.cc
  60. work_queue_sets.h
  61. work_queue_sets_unittest.cc
  62. work_queue_unittest.cc
  63. work_tracker.cc
  64. work_tracker.h
  65. work_tracker_unittest.cc
base/task/sequence_manager/README.md

What is this

This file documents high level parts of the sequence manager.

The sequence manager provides a set of prioritized FIFO task queues, which allows funneling multiple sequences of immediate and delayed tasks on a single underlying sequence.

Work Queue and Task selection

Both immediate tasks and delayed tasks are posted to a TaskQueue via an associated TaskRunner. TaskQueues use distinct primitive FIFO queues, called WorkQueues, to manage immediate tasks and delayed tasks. Tasks eventually end up in their assigned WorkQueue which is made directly visible to SequenceManager through TaskQueueSelector. SequenceManagerImpl::SelectNextTask() uses TaskQueueSelector::SelectWorkQueueToService() to select the next work queue based on various policy e.g. priority, from which 1 task is popped at a time.

Journey of a Task

Task queues have a mechanism to allow efficient cross-thread posting with the use of 2 work queues, immediate_incoming_queue which is used when posting, and immediate_work_queue used to pop tasks from. An immediate task posted from the main thread is pushed on immediate_incoming_queue in TaskQueueImpl::PostImmediateTaskImpl(). If the work queue was empty, SequenceManager is notified and the TaskQueue is registered to do ReloadEmptyImmediateWorkQueue() before SequenceManager selects a task, which moves tasks from immediate_incoming_queue to immediate_work_queue in batch for all registered TaskQueues. The tasks then follow the regular work queue selection mechanism.

Journey of a WakeUp

A WakeUp represents a time at which a delayed task wants to run.

Each TaskQueueImpl maintains its own next wake-up as main_thread_only().scheduled_wake_up, associated with the earliest pending delayed task. It communicates its wake up to the WakeUpQueue via WakeUpQueue::SetNextWakeUpForQueue(). The WakeUpQueue is responsible for determining the single next wake up time for the thread. This is accessed from SequenceManagerImpl and may determine the next run time if there's no immediate work, which ultimately gets passed to the MessagePump, typically via MessagePump::Delegate::NextWorkInfo (returned by ThreadControllerWithMessagePumpImpl::DoWork()) or by MessagePump::ScheduleDelayedWork() (on rare occasions where the next WakeUp is scheduled on the main thread from outside a DoWork()). When a delayed run time associated with a wake-up is reached, WakeUpQueue is notified through WakeUpQueue::MoveReadyDelayedTasksToWorkQueues() and in turn notifies all TaskQueues whose wake-up can be resolved. This lets each TaskQueues process ripe delayed tasks.

Journey of a delayed Task

A delayed Task posted cross-thread generates an immediate Task to run TaskQueueImpl::ScheduleDelayedWorkTask() which eventually calls TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread(), so that it can be enqueued on the main thread. A delayed Task posted from the main thread skips this step and calls TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread() directly. The Task is then pushed on main_thread_only().delayed_incoming_queue and possibly updates the next task queue wake-up. Once the delayed run time is reached, possibly because the wake-up is resolved, the delayed task is moved to main_thread_only().delayed_work_queue and follows the regular work queue selection mechanism.

TimeDomain and TickClock

SequenceManager and related classes use a common TickClock that can be injected by specifying a TimeDomain. A TimeDomain is a specialisation of TickClock that gets notified when the MessagePump is about to go idle via TimeDomain::MaybeFastForwardToWakeUp(), and can use the signal to fast forward in time. This is used in TaskEnvironment to support MOCK_TIME, and in devtools to support virtual time.