// Copyright 2019 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_TASK_THREAD_POOL_TASK_SOURCE_H_ #define BASE_TASK_THREAD_POOL_TASK_SOURCE_H_ #include <stddef.h> #include "base/base_export.h" #include "base/containers/intrusive_heap.h" #include "base/dcheck_is_on.h" #include "base/memory/raw_ptr_exclusion.h" #include "base/memory/ref_counted.h" #include "base/memory/stack_allocated.h" #include "base/sequence_token.h" #include "base/task/common/checked_lock.h" #include "base/task/task_traits.h" #include "base/task/thread_pool/task.h" #include "base/task/thread_pool/task_source_sort_key.h" #include "base/threading/sequence_local_storage_map.h" #include "base/time/time.h" namespace base { namespace internal { class TaskTracker; enum class TaskSourceExecutionMode { … }; struct BASE_EXPORT ExecutionEnvironment { … }; // A TaskSource is a virtual class that provides a series of Tasks that must be // executed immediately or in the future. // // When a task source has delayed tasks but no immediate tasks, the scheduler // must call OnBecomeReady() after HasReadyTasks(now) == true, which is // guaranteed once now >= GetDelayedSortKey(). // // A task source is registered when it's ready to be added to the immediate // queue. A task source is ready to be queued when either: // 1- It has new tasks that can run concurrently as a result of external // operations, e.g. posting a new immediate task to an empty Sequence or // increasing max concurrency of a JobTaskSource; // 2- A worker finished running a task from it and both DidProcessTask() and // WillReEnqueue() returned true; or // 3- A worker is about to run a task from it and WillRunTask() returned // kAllowedNotSaturated. // 4- A delayed task became ready and OnBecomeReady() returns true. // // A worker may perform the following sequence of operations on a // RegisteredTaskSource after obtaining it from the queue: // 1- Check whether a task can run with WillRunTask() (and register/enqueue the // task source again if not saturated). // 2- (optional) Iff (1) determined that a task can run, access the next task // with TakeTask(). // 3- (optional) Execute the task. // 4- Inform the task source that a task was processed with DidProcessTask(), // and re-enqueue the task source iff requested. The task source is ready to // run immediately iff WillReEnqueue() returns true. // When a task source is registered multiple times, many overlapping chains of // operations may run concurrently, as permitted by WillRunTask(). This allows // tasks from the same task source to run in parallel. // However, the following invariants are kept: // - The number of workers concurrently running tasks never goes over the // intended concurrency. // - If the task source has more tasks that can run concurrently, it must be // queued. // // Note: there is a known refcounted-ownership cycle in the ThreadPool // architecture: TaskSource -> TaskRunner -> TaskSource -> ... This is okay so // long as the other owners of TaskSource (PriorityQueue and WorkerThread in // alternation and ThreadGroup::WorkerThreadDelegateImpl::GetWork() // temporarily) keep running it (and taking Tasks from it as a result). A // dangling reference cycle would only occur should they release their reference // to it while it's not empty. In other words, it is only correct for them to // release it when DidProcessTask() returns false. // // This class is thread-safe. class BASE_EXPORT TaskSource : public RefCountedThreadSafe<TaskSource> { … }; // Wrapper around TaskSource to signify the intent to queue and run it. // RegisteredTaskSource can only be created with TaskTracker and may only be // used by a single worker at a time. However, the same task source may be // registered several times, spawning multiple RegisteredTaskSources. A // RegisteredTaskSource resets to its initial state when WillRunTask() fails // or after DidProcessTask() and WillReEnqueue(), so it can be used again. class BASE_EXPORT RegisteredTaskSource { … }; // A pair of Transaction and RegisteredTaskSource. Useful to carry a // RegisteredTaskSource with an associated Transaction. struct BASE_EXPORT RegisteredTaskSourceAndTransaction { … }; struct BASE_EXPORT TaskSourceAndTransaction { … }; } // namespace internal } // namespace base #endif // BASE_TASK_THREAD_POOL_TASK_SOURCE_H_