task_tracker.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_TASK_THREAD_POOL_TASK_TRACKER_H_
  5. #define BASE_TASK_THREAD_POOL_TASK_TRACKER_H_
  6. #include <atomic>
  7. #include <functional>
  8. #include <limits>
  9. #include <memory>
  10. #include <queue>
  11. #include "base/atomicops.h"
  12. #include "base/base_export.h"
  13. #include "base/callback_forward.h"
  14. #include "base/macros.h"
  15. #include "base/metrics/histogram_base.h"
  16. #include "base/sequence_checker.h"
  17. #include "base/strings/string_piece.h"
  18. #include "base/synchronization/waitable_event.h"
  19. #include "base/task/common/checked_lock.h"
  20. #include "base/task/common/task_annotator.h"
  21. #include "base/task/task_traits.h"
  22. #include "base/task/thread_pool/task.h"
  23. #include "base/task/thread_pool/task_source.h"
  24. #include "base/task/thread_pool/tracked_ref.h"
  25. #include "base/thread_annotations.h"
  26. namespace base {
  27. class ConditionVariable;
  28. namespace internal {
  29. // Determines which tasks are allowed to run.
  30. enum class CanRunPolicy {
  31. // All tasks are allowed to run.
  32. kAll,
  33. // Only USER_VISIBLE and USER_BLOCKING tasks are allowed to run.
  34. kForegroundOnly,
  35. // No tasks can run.
  36. kNone,
  37. };
  38. // TaskTracker enforces policies that determines whether:
  39. // - A task can be pushed to a task source (WillPostTask).
  40. // - A task source can be queued (WillQueueTaskSource).
  41. // - Tasks for a given priority can run (CanRunPriority).
  42. // - The next task in a queued task source can run (RunAndPopNextTask).
  43. // TaskTracker also sets up the environment to run a task (RunAndPopNextTask)
  44. // and records metrics and trace events. This class is thread-safe.
  45. class BASE_EXPORT TaskTracker {
  46. public:
  47. // |histogram_label| is used to label histograms. No histograms are recorded
  48. // if it is empty.
  49. TaskTracker(StringPiece histogram_label);
  50. virtual ~TaskTracker();
  51. // Initiates shutdown. Once this is called, only BLOCK_SHUTDOWN tasks will
  52. // start running (doesn't affect tasks that are already running). This can
  53. // only be called once.
  54. void StartShutdown();
  55. // Synchronously completes shutdown. StartShutdown() must be called first.
  56. // Returns when:
  57. // - All SKIP_ON_SHUTDOWN tasks that were already running have completed their
  58. // execution.
  59. // - All posted BLOCK_SHUTDOWN tasks have completed their execution.
  60. // CONTINUE_ON_SHUTDOWN tasks still may be running after Shutdown returns.
  61. // This can only be called once.
  62. void CompleteShutdown();
  63. // Waits until there are no incomplete task sources. May be called in tests
  64. // to validate that a condition is met after all task sources have run.
  65. //
  66. // Does not wait for delayed tasks. Waits for task sources posted from
  67. // other threads during the call. Returns immediately when shutdown completes.
  68. void FlushForTesting();
  69. // Returns and calls |flush_callback| when there are no incomplete undelayed
  70. // tasks. |flush_callback| may be called back on any thread and should not
  71. // perform a lot of work. May be used when additional work on the current
  72. // thread needs to be performed during a flush. Only one
  73. // FlushAsyncForTesting() may be pending at any given time.
  74. void FlushAsyncForTesting(OnceClosure flush_callback);
  75. // Sets the new CanRunPolicy policy, possibly affecting result of
  76. // CanRunPriority(). The caller must wake up worker as appropriate so that
  77. // tasks that are allowed to run by the new policy can be scheduled.
  78. void SetCanRunPolicy(CanRunPolicy can_run_policy);
  79. // Informs this TaskTracker that |task| with |shutdown_behavior| is about to
  80. // be pushed to a task source (if non-delayed) or be added to the
  81. // DelayedTaskManager (if delayed). Returns true if this operation is allowed
  82. // (the operation should be performed if-and-only-if it is). This method may
  83. // also modify metadata on |task| if desired.
  84. bool WillPostTask(Task* task, TaskShutdownBehavior shutdown_behavior);
  85. // Informs this TaskTracker that |task| that is about to be pushed to a task
  86. // source with |priority|. Returns true if this operation is allowed (the
  87. // operation should be performed if-and-only-if it is).
  88. bool WillPostTaskNow(const Task& task,
  89. TaskPriority priority) WARN_UNUSED_RESULT;
  90. // Informs this TaskTracker that |task_source| is about to be queued. Returns
  91. // a RegisteredTaskSource that should be queued if-and-only-if it evaluates to
  92. // true.
  93. RegisteredTaskSource RegisterTaskSource(
  94. scoped_refptr<TaskSource> task_source);
  95. // Returns true if a task with |priority| can run under to the current policy.
  96. bool CanRunPriority(TaskPriority priority) const;
  97. // Runs the next task in |task_source| unless the current shutdown state
  98. // prevents that. Then, pops the task from |task_source| (even if it didn't
  99. // run). Returns |task_source| if non-empty after popping a task from it
  100. // (which indicates that it should be reenqueued). WillPostTask() must have
  101. // allowed the task in front of |task_source| to be posted before this is
  102. // called.
  103. RegisteredTaskSource RunAndPopNextTask(RegisteredTaskSource task_source);
  104. // Returns true once shutdown has started (StartShutdown() was called).
  105. // Note: sequential consistency with the thread calling StartShutdown() isn't
  106. // guaranteed by this call.
  107. bool HasShutdownStarted() const;
  108. // Returns true if shutdown has completed (StartShutdown() was called and
  109. // no tasks are blocking shutdown).
  110. bool IsShutdownComplete() const;
  111. // Records two histograms
  112. // 1. ThreadPool.[label].HeartbeatLatencyMicroseconds.[suffix]:
  113. // Now() - posted_time
  114. // 2. ThreadPool.[label].NumTasksRunWhileQueuing.[suffix]:
  115. // GetNumTasksRun() - num_tasks_run_when_posted.
  116. // [label] is the histogram label provided to the constructor.
  117. // [suffix] is derived from |task_priority|.
  118. void RecordHeartbeatLatencyAndTasksRunWhileQueuingHistograms(
  119. TaskPriority task_priority,
  120. TimeTicks posted_time,
  121. int num_tasks_run_when_posted) const;
  122. // Returns the number of tasks run so far
  123. int GetNumTasksRun() const;
  124. TrackedRef<TaskTracker> GetTrackedRef() {
  125. return tracked_ref_factory_.GetTrackedRef();
  126. }
  127. // Returns true if there are task sources that haven't completed their
  128. // execution (still queued or in progress). If it returns false: the side-
  129. // effects of all completed tasks are guaranteed to be visible to the caller.
  130. bool HasIncompleteTaskSourcesForTesting() const;
  131. protected:
  132. // Runs and deletes |task|. |task| is deleted in the environment where it
  133. // runs. |task_source| is the task source from which |task| was extracted.
  134. // |traits| are the traits of |task_source|. An override is expected to call
  135. // its parent's implementation but is free to perform extra work before and
  136. // after doing so.
  137. virtual void RunTask(Task task,
  138. TaskSource* task_source,
  139. const TaskTraits& traits);
  140. private:
  141. friend class RegisteredTaskSource;
  142. class State;
  143. void PerformShutdown();
  144. // Called before WillPostTask() informs the tracing system that a task has
  145. // been posted. Updates |num_items_blocking_shutdown_| if necessary and
  146. // returns true if the current shutdown state allows the task to be posted.
  147. bool BeforeQueueTaskSource(TaskShutdownBehavior shutdown_behavior);
  148. // Called before a task with |effective_shutdown_behavior| is run by
  149. // RunTask(). Updates |num_items_blocking_shutdown_| if necessary and returns
  150. // true if the current shutdown state allows the task to be run.
  151. bool BeforeRunTask(TaskShutdownBehavior shutdown_behavior);
  152. // Called after a task with |effective_shutdown_behavior| has been run by
  153. // RunTask(). Updates |num_items_blocking_shutdown_| if necessary.
  154. void AfterRunTask(TaskShutdownBehavior shutdown_behavior);
  155. // Informs this TaskTracker that |task_source| won't be reenqueued and returns
  156. // the underlying TaskSource. This is called before destroying a valid
  157. // RegisteredTaskSource. Updates |num_items_blocking_shutdown_| if necessary.
  158. scoped_refptr<TaskSource> UnregisterTaskSource(
  159. scoped_refptr<TaskSource> task_source);
  160. // Called when an item blocking shutdown finishes after shutdown has started.
  161. void DecrementNumItemsBlockingShutdown();
  162. // Decrements the number of incomplete task sources and signals |flush_cv_|
  163. // if it reaches zero.
  164. void DecrementNumIncompleteTaskSources();
  165. // Calls |flush_callback_for_testing_| if one is available in a lock-safe
  166. // manner.
  167. void CallFlushCallbackForTesting();
  168. // Records |Now() - posted_time| to the
  169. // ThreadPool.TaskLatencyMicroseconds.[label].[priority] histogram.
  170. void RecordLatencyHistogram(TaskPriority priority,
  171. TimeTicks posted_time) const;
  172. void IncrementNumTasksRun();
  173. // Dummy frames to allow identification of shutdown behavior in a stack trace.
  174. void RunContinueOnShutdown(Task* task);
  175. void RunSkipOnShutdown(Task* task);
  176. void RunBlockShutdown(Task* task);
  177. void RunTaskWithShutdownBehavior(TaskShutdownBehavior shutdown_behavior,
  178. Task* task);
  179. TaskAnnotator task_annotator_;
  180. // Suffix for histograms recorded by this TaskTracker.
  181. const std::string histogram_label_;
  182. // Indicates whether logging information about TaskPriority::BEST_EFFORT tasks
  183. // was enabled with a command line switch.
  184. const bool has_log_best_effort_tasks_switch_;
  185. // Number of tasks blocking shutdown and boolean indicating whether shutdown
  186. // has started. |shutdown_lock_| should be held to access |shutdown_event_|
  187. // when this indicates that shutdown has started because State doesn't provide
  188. // memory barriers. It intentionally trades having to use a Lock on shutdown
  189. // with not needing memory barriers at runtime.
  190. const std::unique_ptr<State> state_;
  191. // Number of task sources that haven't completed their execution. Is
  192. // decremented with a memory barrier after the last task of a task source
  193. // runs. Is accessed with an acquire memory barrier in FlushForTesting(). The
  194. // memory barriers ensure that the memory written by flushed task sources is
  195. // visible when FlushForTesting() returns.
  196. std::atomic_int num_incomplete_task_sources_{0};
  197. // Global policy the determines result of CanRunPriority().
  198. std::atomic<CanRunPolicy> can_run_policy_;
  199. // Lock associated with |flush_cv_|. Partially synchronizes access to
  200. // |num_incomplete_task_sources_|. Full synchronization isn't needed
  201. // because it's atomic, but synchronization is needed to coordinate waking and
  202. // sleeping at the right time. Fully synchronizes access to
  203. // |flush_callback_for_testing_|.
  204. mutable CheckedLock flush_lock_;
  205. // Signaled when |num_incomplete_task_sources_| is or reaches zero or when
  206. // shutdown completes.
  207. const std::unique_ptr<ConditionVariable> flush_cv_;
  208. // Invoked if non-null when |num_incomplete_task_sources_| is zero or when
  209. // shutdown completes.
  210. OnceClosure flush_callback_for_testing_ GUARDED_BY(flush_lock_);
  211. // Synchronizes access to shutdown related members below.
  212. mutable CheckedLock shutdown_lock_;
  213. // Event instantiated when shutdown starts and signaled when shutdown
  214. // completes.
  215. std::unique_ptr<WaitableEvent> shutdown_event_ GUARDED_BY(shutdown_lock_);
  216. // Counter for number of tasks run so far, used to record tasks run while
  217. // a task queued to histogram.
  218. std::atomic_int num_tasks_run_{0};
  219. // ThreadPool.TaskLatencyMicroseconds.*,
  220. // ThreadPool.HeartbeatLatencyMicroseconds.*, and
  221. // ThreadPool.NumTasksRunWhileQueuing.* histograms. The index is a
  222. // TaskPriority. Intentionally leaked.
  223. // TODO(scheduler-dev): Consider using STATIC_HISTOGRAM_POINTER_GROUP for
  224. // these.
  225. using TaskPriorityType = std::underlying_type<TaskPriority>::type;
  226. static constexpr TaskPriorityType kNumTaskPriorities =
  227. static_cast<TaskPriorityType>(TaskPriority::HIGHEST) + 1;
  228. HistogramBase* const task_latency_histograms_[kNumTaskPriorities];
  229. HistogramBase* const heartbeat_latency_histograms_[kNumTaskPriorities];
  230. HistogramBase* const
  231. num_tasks_run_while_queuing_histograms_[kNumTaskPriorities];
  232. // Ensures all state (e.g. dangling cleaned up workers) is coalesced before
  233. // destroying the TaskTracker (e.g. in test environments).
  234. // Ref. https://crbug.com/827615.
  235. TrackedRefFactory<TaskTracker> tracked_ref_factory_;
  236. DISALLOW_COPY_AND_ASSIGN(TaskTracker);
  237. };
  238. } // namespace internal
  239. } // namespace base
  240. #endif // BASE_TASK_THREAD_POOL_TASK_TRACKER_H_