diff options
Diffstat (limited to 'chromium/base/task/post_job.h')
-rw-r--r-- | chromium/base/task/post_job.h | 100 |
1 files changed, 97 insertions, 3 deletions
diff --git a/chromium/base/task/post_job.h b/chromium/base/task/post_job.h index de6b2d66ac3..cf8ca1aec70 100644 --- a/chromium/base/task/post_job.h +++ b/chromium/base/task/post_job.h @@ -6,8 +6,12 @@ #define BASE_TASK_POST_JOB_H_ #include "base/base_export.h" +#include "base/callback.h" +#include "base/location.h" #include "base/logging.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/task/task_traits.h" #include "base/time/time.h" namespace base { @@ -23,8 +27,9 @@ class BASE_EXPORT JobDelegate { public: // A JobDelegate is instantiated for each worker task that is run. // |task_source| is the task source whose worker task is running with this - // delegate and |pooled_task_runner_delegate| provides communication with the - // thread pool. + // delegate and |pooled_task_runner_delegate| is used by ShouldYield() to + // check whether the pool wants this worker task to yield (null if this worker + // should never yield -- e.g. when the main thread is a worker). JobDelegate(internal::JobTaskSource* task_source, internal::PooledTaskRunnerDelegate* pooled_task_runner_delegate); ~JobDelegate(); @@ -42,7 +47,7 @@ class BASE_EXPORT JobDelegate { void YieldIfNeeded(); // Notifies the scheduler that max concurrency was increased, and the number - // of worker should be adjusted. + // of worker should be adjusted accordingly. See PostJob() for more details. void NotifyConcurrencyIncrease(); private: @@ -67,6 +72,95 @@ class BASE_EXPORT JobDelegate { DISALLOW_COPY_AND_ASSIGN(JobDelegate); }; +// Handle returned when posting a Job. Provides methods to control execution of +// the posted Job. +class BASE_EXPORT JobHandle { + public: + JobHandle(); + // A job must either be joined, canceled or detached before the JobHandle is + // destroyed. + ~JobHandle(); + + JobHandle(JobHandle&&); + JobHandle& operator=(JobHandle&&); + + // Update this Job's priority. + void UpdatePriority(TaskPriority new_priority); + + // Notifies the scheduler that max concurrency was increased, and the number + // of workers should be adjusted accordingly. See PostJob() for more details. + void NotifyConcurrencyIncrease(); + + // Contributes to the job on this thread. Doesn't return until all tasks have + // completed and max concurrency becomes 0. This also promotes this Job's + // priority to be at least as high as the calling thread's priority. + void Join(); + + // Forces all existing workers to yield ASAP. Waits until they have all + // returned from the Job's callback before returning. + void Cancel(); + + // Forces all existing workers to yield ASAP but doesn’t wait for them. + // Warning, this is dangerous if the Job's callback is bound to or has access + // to state which may be deleted after this call. + void CancelAndDetach(); + + // Can be invoked before ~JobHandle() to avoid waiting on the job completing. + void Detach(); + + private: + friend class internal::JobTaskSource; + + explicit JobHandle(scoped_refptr<internal::JobTaskSource> task_source); + + scoped_refptr<internal::JobTaskSource> task_source_; + + DISALLOW_COPY_AND_ASSIGN(JobHandle); +}; + +// Posts a repeating |worker_task| with specific |traits| to run in parallel. +// Returns a JobHandle associated with the Job, which can be joined, canceled or +// detached. +// To avoid scheduling overhead, |worker_task| should do as much work as +// possible in a loop when invoked, and JobDelegate::ShouldYield() should be +// periodically invoked to conditionally exit and let the scheduler prioritize +// work. +// +// A canonical implementation of |worker_task| looks like: +// void WorkerTask(JobDelegate* job_delegate) { +// while (!job_delegate->ShouldYield()) { +// auto work_item = worker_queue.TakeWorkItem(); // Smallest unit of work. +// if (!work_item) +// return: +// ProcessWork(work_item); +// } +// } +// +// |max_concurrency_callback| controls the maximum number of threads calling +// |worker_task| concurrently. |worker_task| is only invoked if the number of +// threads previously running |worker_task| was less than the value returned by +// |max_concurrency_callback|. In general, |max_concurrency_callback| should +// return the latest number of incomplete work items (smallest unit of work) +// left to processed. JobHandle/JobDelegate::NotifyConcurrencyIncrease() *must* +// be invoked shortly after |max_concurrency_callback| starts returning a value +// larger than previously returned values. This usually happens when new work +// items are added and the API user wants additional threads to invoke +// |worker_task| concurrently. The callbacks may be called concurrently on any +// thread until the job is complete. If the job handle is detached, the +// callbacks may still be called, so they must not access global state that +// could be destroyed. +// +// |traits| requirements: +// - base::ThreadPool() must be specified. +// - Extension traits (e.g. BrowserThread) cannot be specified. +// - base::ThreadPolicy must be specified if the priority of the task runner +// will ever be increased from BEST_EFFORT. +JobHandle BASE_EXPORT +PostJob(const Location& from_here, + const TaskTraits& traits, + RepeatingCallback<void(JobDelegate*)> worker_task, + RepeatingCallback<size_t()> max_concurrency_callback); + } // namespace experimental } // namespace base |