task_queue.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // Copyright 2018 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_SEQUENCE_MANAGER_TASK_QUEUE_H_
  5. #define BASE_TASK_SEQUENCE_MANAGER_TASK_QUEUE_H_
  6. #include <memory>
  7. #include "base/memory/weak_ptr.h"
  8. #include "base/optional.h"
  9. #include "base/single_thread_task_runner.h"
  10. #include "base/task/common/checked_lock.h"
  11. #include "base/task/sequence_manager/lazy_now.h"
  12. #include "base/task/sequence_manager/tasks.h"
  13. #include "base/task/task_observer.h"
  14. #include "base/threading/platform_thread.h"
  15. #include "base/time/time.h"
  16. namespace base {
  17. class TaskObserver;
  18. namespace trace_event {
  19. class BlameContext;
  20. }
  21. namespace sequence_manager {
  22. namespace internal {
  23. class AssociatedThreadId;
  24. class SequenceManagerImpl;
  25. class TaskQueueImpl;
  26. } // namespace internal
  27. class TimeDomain;
  28. // TODO(kraynov): Make TaskQueue to actually be an interface for TaskQueueImpl
  29. // and stop using ref-counting because we're no longer tied to task runner
  30. // lifecycle and there's no other need for ref-counting either.
  31. // NOTE: When TaskQueue gets automatically deleted on zero ref-count,
  32. // TaskQueueImpl gets gracefully shutdown. It means that it doesn't get
  33. // unregistered immediately and might accept some last minute tasks until
  34. // SequenceManager will unregister it at some point. It's done to ensure that
  35. // task queue always gets unregistered on the main thread.
  36. class BASE_EXPORT TaskQueue : public RefCountedThreadSafe<TaskQueue> {
  37. public:
  38. class Observer {
  39. public:
  40. virtual ~Observer() = default;
  41. // Notify observer that the time at which this queue wants to run
  42. // the next task has changed. |next_wakeup| can be in the past
  43. // (e.g. TimeTicks() can be used to notify about immediate work).
  44. // Can be called on any thread
  45. // All methods but SetObserver, SetTimeDomain and GetTimeDomain can be
  46. // called on |queue|.
  47. //
  48. // TODO(altimin): Make it Optional<TimeTicks> to tell
  49. // observer about cancellations.
  50. virtual void OnQueueNextWakeUpChanged(TimeTicks next_wake_up) = 0;
  51. };
  52. // Shuts down the queue. All tasks currently queued will be discarded.
  53. virtual void ShutdownTaskQueue();
  54. // Shuts down the queue when there are no more tasks queued.
  55. void ShutdownTaskQueueGracefully();
  56. // TODO(scheduler-dev): Could we define a more clear list of priorities?
  57. // See https://crbug.com/847858.
  58. enum QueuePriority : uint8_t {
  59. // Queues with control priority will run before any other queue, and will
  60. // explicitly starve other queues. Typically this should only be used for
  61. // private queues which perform control operations.
  62. kControlPriority = 0,
  63. // The selector will prioritize highest over high, normal and low; and
  64. // high over normal and low; and normal over low. However it will ensure
  65. // neither of the lower priority queues can be completely starved by higher
  66. // priority tasks. All three of these queues will always take priority over
  67. // and can starve the best effort queue.
  68. kHighestPriority = 1,
  69. kVeryHighPriority = 2,
  70. kHighPriority = 3,
  71. // Queues with normal priority are the default.
  72. kNormalPriority = 4,
  73. kLowPriority = 5,
  74. // Queues with best effort priority will only be run if all other queues are
  75. // empty. They can be starved by the other queues.
  76. kBestEffortPriority = 6,
  77. // Must be the last entry.
  78. kQueuePriorityCount = 7,
  79. kFirstQueuePriority = kControlPriority,
  80. };
  81. // Can be called on any thread.
  82. static const char* PriorityToString(QueuePriority priority);
  83. // Options for constructing a TaskQueue.
  84. struct Spec {
  85. explicit Spec(const char* name) : name(name) {}
  86. Spec SetShouldMonitorQuiescence(bool should_monitor) {
  87. should_monitor_quiescence = should_monitor;
  88. return *this;
  89. }
  90. Spec SetShouldNotifyObservers(bool run_observers) {
  91. should_notify_observers = run_observers;
  92. return *this;
  93. }
  94. // Delayed fences require Now() to be sampled when posting immediate tasks
  95. // which is not free.
  96. Spec SetDelayedFencesAllowed(bool allow_delayed_fences) {
  97. delayed_fence_allowed = allow_delayed_fences;
  98. return *this;
  99. }
  100. Spec SetTimeDomain(TimeDomain* domain) {
  101. time_domain = domain;
  102. return *this;
  103. }
  104. const char* name;
  105. bool should_monitor_quiescence = false;
  106. TimeDomain* time_domain = nullptr;
  107. bool should_notify_observers = true;
  108. bool delayed_fence_allowed = false;
  109. };
  110. // TODO(altimin): Make this private after TaskQueue/TaskQueueImpl refactoring.
  111. TaskQueue(std::unique_ptr<internal::TaskQueueImpl> impl,
  112. const TaskQueue::Spec& spec);
  113. TaskQueue(const TaskQueue&) = delete;
  114. TaskQueue& operator=(const TaskQueue&) = delete;
  115. // Information about task execution.
  116. //
  117. // Wall-time related methods (start_time, end_time, wall_duration) can be
  118. // called only when |has_wall_time()| is true.
  119. // Thread-time related mehtods (start_thread_time, end_thread_time,
  120. // thread_duration) can be called only when |has_thread_time()| is true.
  121. //
  122. // start_* should be called after RecordTaskStart.
  123. // end_* and *_duration should be called after RecordTaskEnd.
  124. class BASE_EXPORT TaskTiming {
  125. public:
  126. enum class State { NotStarted, Running, Finished };
  127. enum class TimeRecordingPolicy { DoRecord, DoNotRecord };
  128. TaskTiming(bool has_wall_time, bool has_thread_time);
  129. bool has_wall_time() const { return has_wall_time_; }
  130. bool has_thread_time() const { return has_thread_time_; }
  131. base::TimeTicks start_time() const {
  132. DCHECK(has_wall_time());
  133. return start_time_;
  134. }
  135. base::TimeTicks end_time() const {
  136. DCHECK(has_wall_time());
  137. return end_time_;
  138. }
  139. base::TimeDelta wall_duration() const {
  140. DCHECK(has_wall_time());
  141. return end_time_ - start_time_;
  142. }
  143. base::ThreadTicks start_thread_time() const {
  144. DCHECK(has_thread_time());
  145. return start_thread_time_;
  146. }
  147. base::ThreadTicks end_thread_time() const {
  148. DCHECK(has_thread_time());
  149. return end_thread_time_;
  150. }
  151. base::TimeDelta thread_duration() const {
  152. DCHECK(has_thread_time());
  153. return end_thread_time_ - start_thread_time_;
  154. }
  155. State state() const { return state_; }
  156. void RecordTaskStart(LazyNow* now);
  157. void RecordTaskEnd(LazyNow* now);
  158. // Protected for tests.
  159. protected:
  160. State state_ = State::NotStarted;
  161. bool has_wall_time_;
  162. bool has_thread_time_;
  163. base::TimeTicks start_time_;
  164. base::TimeTicks end_time_;
  165. base::ThreadTicks start_thread_time_;
  166. base::ThreadTicks end_thread_time_;
  167. };
  168. // An interface that lets the owner vote on whether or not the associated
  169. // TaskQueue should be enabled.
  170. class BASE_EXPORT QueueEnabledVoter {
  171. public:
  172. ~QueueEnabledVoter();
  173. QueueEnabledVoter(const QueueEnabledVoter&) = delete;
  174. const QueueEnabledVoter& operator=(const QueueEnabledVoter&) = delete;
  175. // Votes to enable or disable the associated TaskQueue. The TaskQueue will
  176. // only be enabled if all the voters agree it should be enabled, or if there
  177. // are no voters.
  178. // NOTE this must be called on the thread the associated TaskQueue was
  179. // created on.
  180. void SetVoteToEnable(bool enabled);
  181. bool IsVotingToEnable() const { return enabled_; }
  182. private:
  183. friend class TaskQueue;
  184. explicit QueueEnabledVoter(scoped_refptr<TaskQueue> task_queue);
  185. scoped_refptr<TaskQueue> const task_queue_;
  186. bool enabled_;
  187. };
  188. // Returns an interface that allows the caller to vote on whether or not this
  189. // TaskQueue is enabled. The TaskQueue will be enabled if there are no voters
  190. // or if all agree it should be enabled.
  191. // NOTE this must be called on the thread this TaskQueue was created by.
  192. std::unique_ptr<QueueEnabledVoter> CreateQueueEnabledVoter();
  193. // NOTE this must be called on the thread this TaskQueue was created by.
  194. bool IsQueueEnabled() const;
  195. // Returns true if the queue is completely empty.
  196. bool IsEmpty() const;
  197. // Returns the number of pending tasks in the queue.
  198. size_t GetNumberOfPendingTasks() const;
  199. // Returns true if the queue has work that's ready to execute now.
  200. // NOTE: this must be called on the thread this TaskQueue was created by.
  201. bool HasTaskToRunImmediately() const;
  202. // Returns requested run time of next scheduled wake-up for a delayed task
  203. // which is not ready to run. If there are no such tasks (immediate tasks
  204. // don't count) or the queue is disabled it returns nullopt.
  205. // NOTE: this must be called on the thread this TaskQueue was created by.
  206. Optional<TimeTicks> GetNextScheduledWakeUp();
  207. // Can be called on any thread.
  208. virtual const char* GetName() const;
  209. // Set the priority of the queue to |priority|. NOTE this must be called on
  210. // the thread this TaskQueue was created by.
  211. void SetQueuePriority(QueuePriority priority);
  212. // Returns the current queue priority.
  213. QueuePriority GetQueuePriority() const;
  214. // These functions can only be called on the same thread that the task queue
  215. // manager executes its tasks on.
  216. void AddTaskObserver(TaskObserver* task_observer);
  217. void RemoveTaskObserver(TaskObserver* task_observer);
  218. // Set the blame context which is entered and left while executing tasks from
  219. // this task queue. |blame_context| must be null or outlive this task queue.
  220. // Must be called on the thread this TaskQueue was created by.
  221. void SetBlameContext(trace_event::BlameContext* blame_context);
  222. // Removes the task queue from the previous TimeDomain and adds it to
  223. // |domain|. This is a moderately expensive operation.
  224. void SetTimeDomain(TimeDomain* domain);
  225. // Returns the queue's current TimeDomain. Can be called from any thread.
  226. TimeDomain* GetTimeDomain() const;
  227. enum class InsertFencePosition {
  228. kNow, // Tasks posted on the queue up till this point further may run.
  229. // All further tasks are blocked.
  230. kBeginningOfTime, // No tasks posted on this queue may run.
  231. };
  232. // Inserts a barrier into the task queue which prevents tasks with an enqueue
  233. // order greater than the fence from running until either the fence has been
  234. // removed or a subsequent fence has unblocked some tasks within the queue.
  235. // Note: delayed tasks get their enqueue order set once their delay has
  236. // expired, and non-delayed tasks get their enqueue order set when posted.
  237. //
  238. // Fences come in three flavours:
  239. // - Regular (InsertFence(NOW)) - all tasks posted after this moment
  240. // are blocked.
  241. // - Fully blocking (InsertFence(kBeginningOfTime)) - all tasks including
  242. // already posted are blocked.
  243. // - Delayed (InsertFenceAt(timestamp)) - blocks all tasks posted after given
  244. // point in time (must be in the future).
  245. //
  246. // Only one fence can be scheduled at a time. Inserting a new fence
  247. // will automatically remove the previous one, regardless of fence type.
  248. void InsertFence(InsertFencePosition position);
  249. // Delayed fences are only allowed for queues created with
  250. // SetDelayedFencesAllowed(true) because this feature implies sampling Now()
  251. // (which isn't free) for every PostTask, even those with zero delay.
  252. void InsertFenceAt(TimeTicks time);
  253. // Removes any previously added fence and unblocks execution of any tasks
  254. // blocked by it.
  255. void RemoveFence();
  256. // Returns true if the queue has a fence but it isn't necessarily blocking
  257. // execution of tasks (it may be the case if tasks enqueue order hasn't
  258. // reached the number set for a fence).
  259. bool HasActiveFence();
  260. // Returns true if the queue has a fence which is blocking execution of tasks.
  261. bool BlockedByFence() const;
  262. void SetObserver(Observer* observer);
  263. // Controls whether or not the queue will emit traces events when tasks are
  264. // posted to it while disabled. This only applies for the current or next
  265. // period during which the queue is disabled. When the queue is re-enabled
  266. // this will revert back to the default value of false.
  267. void SetShouldReportPostedTasksWhenDisabled(bool should_report);
  268. // Create a task runner for this TaskQueue which will annotate all
  269. // posted tasks with the given task type.
  270. // May be called on any thread.
  271. // NOTE: Task runners don't hold a reference to a TaskQueue, hence,
  272. // it's required to retain that reference to prevent automatic graceful
  273. // shutdown. Unique ownership of task queues will fix this issue soon.
  274. scoped_refptr<SingleThreadTaskRunner> CreateTaskRunner(TaskType task_type);
  275. // Default task runner which doesn't annotate tasks with a task type.
  276. scoped_refptr<SingleThreadTaskRunner> task_runner() const {
  277. return default_task_runner_;
  278. }
  279. protected:
  280. virtual ~TaskQueue();
  281. internal::TaskQueueImpl* GetTaskQueueImpl() const { return impl_.get(); }
  282. private:
  283. friend class RefCountedThreadSafe<TaskQueue>;
  284. friend class internal::SequenceManagerImpl;
  285. friend class internal::TaskQueueImpl;
  286. void AddQueueEnabledVoter(bool voter_is_enabled);
  287. void RemoveQueueEnabledVoter(bool voter_is_enabled);
  288. bool AreAllQueueEnabledVotersEnabled() const;
  289. void OnQueueEnabledVoteChanged(bool enabled);
  290. bool IsOnMainThread() const;
  291. // TaskQueue has ownership of an underlying implementation but in certain
  292. // cases (e.g. detached frames) their lifetime may diverge.
  293. // This method should be used to take away the impl for graceful shutdown.
  294. // TaskQueue will disregard any calls or posting tasks thereafter.
  295. std::unique_ptr<internal::TaskQueueImpl> TakeTaskQueueImpl();
  296. // |impl_| can be written to on the main thread but can be read from
  297. // any thread.
  298. // |impl_lock_| must be acquired when writing to |impl_| or when accessing
  299. // it from non-main thread. Reading from the main thread does not require
  300. // a lock.
  301. mutable base::internal::CheckedLock impl_lock_{
  302. base::internal::UniversalPredecessor{}};
  303. std::unique_ptr<internal::TaskQueueImpl> impl_;
  304. const WeakPtr<internal::SequenceManagerImpl> sequence_manager_;
  305. scoped_refptr<internal::AssociatedThreadId> associated_thread_;
  306. scoped_refptr<SingleThreadTaskRunner> default_task_runner_;
  307. int enabled_voter_count_ = 0;
  308. int voter_count_ = 0;
  309. const char* name_;
  310. };
  311. } // namespace sequence_manager
  312. } // namespace base
  313. #endif // BASE_TASK_SEQUENCE_MANAGER_TASK_QUEUE_H_