• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_TASK_SEQUENCED_TASK_RUNNER_H_
6 #define BASE_TASK_SEQUENCED_TASK_RUNNER_H_
7 
8 #include <memory>
9 
10 #include "base/auto_reset.h"
11 #include "base/base_export.h"
12 #include "base/functional/callback.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/memory/raw_ptr_exclusion.h"
15 #include "base/task/delay_policy.h"
16 #include "base/task/delayed_task_handle.h"
17 #include "base/task/sequenced_task_runner_helpers.h"
18 #include "base/task/task_runner.h"
19 #include "base/types/pass_key.h"
20 
21 namespace blink {
22 class LowPrecisionTimer;
23 class ScriptedIdleTaskController;
24 class TimerBase;
25 class TimerBasedTickProvider;
26 class WebRtcTaskQueue;
27 }
28 namespace IPC {
29 class ChannelAssociatedGroupController;
30 }  // namespace IPC
31 namespace media {
32 class AlsaPcmOutputStream;
33 class AlsaPcmInputStream;
34 class FakeAudioWorker;
35 }  // namespace media
36 namespace viz {
37 class ExternalBeginFrameSourceWin;
38 }  // namespace viz
39 namespace webrtc {
40 class ThreadWrapper;
41 }  // namespace webrtc
42 
43 namespace base {
44 
45 namespace android {
46 class PreFreezeBackgroundMemoryTrimmer;
47 }
48 namespace internal {
49 class DelayTimerBase;
50 class DelayedTaskManager;
51 }
52 class DeadlineTimer;
53 class MetronomeTimer;
54 class SingleThreadTaskRunner;
55 class TimeDelta;
56 class TimeTicks;
57 
58 namespace subtle {
59 
60 // Restricts access to PostCancelableDelayedTask*() to authorized callers.
61 class PostDelayedTaskPassKey {
62  private:
63   // Avoid =default to disallow creation by uniform initialization.
64   PostDelayedTaskPassKey() = default;
65 
66   friend class base::internal::DelayTimerBase;
67   friend class base::internal::DelayedTaskManager;
68   friend class base::DeadlineTimer;
69   friend class base::MetronomeTimer;
70   friend class blink::LowPrecisionTimer;
71   friend class blink::ScriptedIdleTaskController;
72   friend class blink::TimerBase;
73   friend class blink::TimerBasedTickProvider;
74   friend class blink::WebRtcTaskQueue;
75   friend class PostDelayedTaskPassKeyForTesting;
76   friend class webrtc::ThreadWrapper;
77   friend class media::AlsaPcmOutputStream;
78   friend class media::AlsaPcmInputStream;
79   friend class media::FakeAudioWorker;
80 #if BUILDFLAG(IS_ANDROID)
81   friend class base::android::PreFreezeBackgroundMemoryTrimmer;
82 #endif
83 };
84 
85 // Restricts access to RunOrPostTask() to authorized callers.
86 class RunOrPostTaskPassKey {
87  private:
88   // Avoid =default to disallow creation by uniform initialization.
89   RunOrPostTaskPassKey() = default;
90 
91   friend class IPC::ChannelAssociatedGroupController;
92   friend class RunOrPostTaskPassKeyForTesting;
93   friend class viz::ExternalBeginFrameSourceWin;
94 };
95 
96 class PostDelayedTaskPassKeyForTesting : public PostDelayedTaskPassKey {};
97 class RunOrPostTaskPassKeyForTesting : public RunOrPostTaskPassKey {};
98 
99 }  // namespace subtle
100 
101 // A SequencedTaskRunner is a subclass of TaskRunner that provides
102 // additional guarantees on the order that tasks are started, as well
103 // as guarantees on when tasks are in sequence, i.e. one task finishes
104 // before the other one starts.
105 //
106 // Summary
107 // -------
108 // Non-nested tasks with the same delay will run one by one in FIFO
109 // order.
110 //
111 // Detailed guarantees
112 // -------------------
113 //
114 // SequencedTaskRunner also adds additional methods for posting
115 // non-nestable tasks.  In general, an implementation of TaskRunner
116 // may expose task-running methods which are themselves callable from
117 // within tasks.  A non-nestable task is one that is guaranteed to not
118 // be run from within an already-running task.  Conversely, a nestable
119 // task (the default) is a task that can be run from within an
120 // already-running task.
121 //
122 // The guarantees of SequencedTaskRunner are as follows:
123 //
124 //   - Given two tasks T2 and T1, T2 will start after T1 starts if:
125 //
126 //       * T2 is posted after T1; and
127 //       * T2 has equal or higher delay than T1; and
128 //       * T2 is non-nestable or T1 is nestable.
129 //
130 //   - If T2 will start after T1 starts by the above guarantee, then
131 //     T2 will start after T1 finishes and is destroyed if:
132 //
133 //       * T2 is non-nestable, or
134 //       * T1 doesn't call any task-running methods.
135 //
136 //   - If T2 will start after T1 finishes by the above guarantee, then
137 //     all memory changes in T1 and T1's destruction will be visible
138 //     to T2.
139 //
140 //   - If T2 runs nested within T1 via a call to the task-running
141 //     method M, then all memory changes in T1 up to the call to M
142 //     will be visible to T2, and all memory changes in T2 will be
143 //     visible to T1 from the return from M.
144 //
145 // Note that SequencedTaskRunner does not guarantee that tasks are run
146 // on a single dedicated thread, although the above guarantees provide
147 // most (but not all) of the same guarantees.  If you do need to
148 // guarantee that tasks are run on a single dedicated thread, see
149 // SingleThreadTaskRunner (in single_thread_task_runner.h).
150 //
151 // Some corollaries to the above guarantees, assuming the tasks in
152 // question don't call any task-running methods:
153 //
154 //   - Tasks posted via PostTask are run in FIFO order.
155 //
156 //   - Tasks posted via PostNonNestableTask are run in FIFO order.
157 //
158 //   - Tasks posted with the same delay and the same nestable state
159 //     are run in FIFO order.
160 //
161 //   - A list of tasks with the same nestable state posted in order of
162 //     non-decreasing delay is run in FIFO order.
163 //
164 //   - A list of tasks posted in order of non-decreasing delay with at
165 //     most a single change in nestable state from nestable to
166 //     non-nestable is run in FIFO order. (This is equivalent to the
167 //     statement of the first guarantee above.)
168 //
169 // Some theoretical implementations of SequencedTaskRunner:
170 //
171 //   - A SequencedTaskRunner that wraps a regular TaskRunner but makes
172 //     sure that only one task at a time is posted to the TaskRunner,
173 //     with appropriate memory barriers in between tasks.
174 //
175 //   - A SequencedTaskRunner that, for each task, spawns a joinable
176 //     thread to run that task and immediately quit, and then
177 //     immediately joins that thread.
178 //
179 //   - A SequencedTaskRunner that stores the list of posted tasks and
180 //     has a method Run() that runs each runnable task in FIFO order
181 //     that can be called from any thread, but only if another
182 //     (non-nested) Run() call isn't already happening.
183 //
184 // SequencedTaskRunner::GetCurrentDefault() can be used while running
185 // a task to retrieve the default SequencedTaskRunner for the current
186 // sequence.
187 class BASE_EXPORT SequencedTaskRunner : public TaskRunner {
188  public:
189   // The two PostNonNestable*Task methods below are like their
190   // nestable equivalents in TaskRunner, but they guarantee that the
191   // posted task will not run nested within an already-running task.
192   //
193   // A simple corollary is that posting a task as non-nestable can
194   // only delay when the task gets run.  That is, posting a task as
195   // non-nestable may not affect when the task gets run, or it could
196   // make it run later than it normally would, but it won't make it
197   // run earlier than it normally would.
198 
199   // TODO(akalin): Get rid of the boolean return value for the methods
200   // below.
201 
202   bool PostNonNestableTask(const Location& from_here, OnceClosure task);
203 
204   virtual bool PostNonNestableDelayedTask(const Location& from_here,
205                                           OnceClosure task,
206                                           base::TimeDelta delay) = 0;
207 
208   // Posts the given |task| to be run only after |delay| has passed. Returns a
209   // handle that can be used to cancel the task. This should not be used
210   // directly. Consider using higher level timer primitives in
211   // base/timer/timer.h.
212   //
213   // The handle is only guaranteed valid while the task is pending execution.
214   // This means that it may be invalid if the posting failed, and will be
215   // invalid while the task is executing. Calling CancelTask() on an invalid
216   // handle is a no-op.
217   //
218   // This method and the handle it returns are not thread-safe and can only be
219   // used from the sequence this task runner runs its tasks on.
220   virtual DelayedTaskHandle PostCancelableDelayedTask(
221       subtle::PostDelayedTaskPassKey,
222       const Location& from_here,
223       OnceClosure task,
224       TimeDelta delay);
225 
226   // Posts the given |task| to be run at |delayed_run_time| (or immediately if
227   // in the past), following |delay_policy|. Returns a handle that can be used
228   // to cancel the task. This should not be used directly. Consider using higher
229   // level timer primitives in base/timer/timer.h.
230   [[nodiscard]] virtual DelayedTaskHandle PostCancelableDelayedTaskAt(
231       subtle::PostDelayedTaskPassKey,
232       const Location& from_here,
233       OnceClosure task,
234       TimeTicks delayed_run_time,
235       subtle::DelayPolicy delay_policy);
236 
237   // Posts the given |task| to be run at |delayed_run_time| (or immediately if
238   // in the past), following |delay_policy|. This is used by the default
239   // implementation of PostCancelableDelayedTaskAt(). The default behavior
240   // subtracts TimeTicks::Now() from |delayed_run_time| to get a delay. See
241   // base::Timer to post precise/repeating timeouts.
242   // TODO(crbug.com/40158967): Make pure virtual once all SequencedTaskRunners
243   // implement this.
244   virtual bool PostDelayedTaskAt(subtle::PostDelayedTaskPassKey,
245                                  const Location& from_here,
246                                  OnceClosure task,
247                                  TimeTicks delayed_run_time,
248                                  subtle::DelayPolicy delay_policy);
249 
250   // May run `task` synchronously if no work that has ordering or mutual
251   // exclusion expectations with tasks from this `SequencedTaskRunner` is
252   // pending or running (if such work arrives after `task` starts running
253   // synchronously, it waits until `task` finishes). Otherwise, behaves like
254   // `PostTask`. Since `task` may run synchronously, it is generally not
255   // appropriate to invoke this if `task` may take a long time to run.
256   //
257   // TODO(crbug.com/40944462): This API is still in development. It doesn't yet
258   // support SequenceLocalStorage.
259   virtual bool RunOrPostTask(subtle::RunOrPostTaskPassKey,
260                              const Location& from_here,
261                              OnceClosure task);
262 
263   // Submits a non-nestable task to delete the given object.  Returns
264   // true if the object may be deleted at some point in the future,
265   // and false if the object definitely will not be deleted.
266   //
267   // By default, this leaks `object` if the deleter task doesn't run, e.g. if
268   // the underlying task queue is shut down first. Subclasses can override this
269   // behavior by specializing `DeleteOrReleaseSoonInternal()`.
270   template <class T>
DeleteSoon(const Location & from_here,const T * object)271   bool DeleteSoon(const Location& from_here, const T* object) {
272     return DeleteOrReleaseSoonInternal(from_here, &DeleteHelper<T>::DoDelete,
273                                        object);
274   }
275 
276   template <class T>
DeleteSoon(const Location & from_here,std::unique_ptr<T> object)277   bool DeleteSoon(const Location& from_here, std::unique_ptr<T> object) {
278     return DeleteOrReleaseSoonInternal(
279         from_here, &DeleteUniquePtrHelper<T>::DoDelete, object.release());
280   }
281 
282   // Submits a non-nestable task to release the given object.
283   //
284   // By default, this leaks `object` if the releaser task doesn't run, e.g. if
285   // the underlying task queue is shut down first. Subclasses can override this
286   // behavior by specializing `DeleteOrReleaseSoonInternal()`.
287   //
288   // ReleaseSoon makes sure that the object it the scoped_refptr points to gets
289   // properly released on the correct thread.
290   // We apply ReleaseSoon to the rvalue as the side-effects can be unclear to
291   // the caller if an lvalue is used. That being so, the scoped_refptr should
292   // always be std::move'd.
293   // Example use:
294   //
295   // scoped_refptr<T> foo_scoped_refptr;
296   // ...
297   // task_runner->ReleaseSoon(std::move(foo_scoped_refptr));
298   template <class T>
ReleaseSoon(const Location & from_here,scoped_refptr<T> && object)299   void ReleaseSoon(const Location& from_here, scoped_refptr<T>&& object) {
300     if (!object)
301       return;
302 
303     DeleteOrReleaseSoonInternal(from_here, &ReleaseHelper<T>::DoRelease,
304                                 object.release());
305   }
306 
307   // Returns true iff tasks posted to this TaskRunner are sequenced
308   // with this call.
309   //
310   // In particular:
311   // - Returns true if this is a SequencedTaskRunner to which the
312   //   current task was posted.
313   // - Returns true if this is a SequencedTaskRunner bound to the
314   //   same sequence as the SequencedTaskRunner to which the current
315   //   task was posted.
316   // - Returns true if this is a SingleThreadTaskRunner bound to
317   //   the current thread.
318   virtual bool RunsTasksInCurrentSequence() const = 0;
319 
320   // Returns the default SequencedTaskRunner for the current task. It
321   // should only be called if HasCurrentDefault() returns true (see the comment
322   // there for the requirements).
323   //
324   // It is "default" in the sense that if the current sequence multiplexes
325   // multiple task queues (e.g. BrowserThread::UI), this will return the default
326   // task queue. A caller that wants a specific task queue should obtain it
327   // directly instead of going through this API.
328   //
329   // See
330   // https://chromium.googlesource.com/chromium/src/+/main/docs/threading_and_tasks.md#Posting-to-the-Current-Virtual_Thread
331   // for details
332   [[nodiscard]] static const scoped_refptr<SequencedTaskRunner>&
333   GetCurrentDefault();
334 
335   // Returns true if one of the following conditions is fulfilled:
336   // a) A SequencedTaskRunner has been assigned to the current thread by
337   //    instantiating a SequencedTaskRunner::CurrentDefaultHandle.
338   // b) The current thread has a SingleThreadTaskRunner::CurrentDefaultHandle
339   //    (which includes any thread that runs a MessagePump).
340   [[nodiscard]] static bool HasCurrentDefault();
341 
342   class BASE_EXPORT CurrentDefaultHandle {
343    public:
344     // Sets the value returned by `SequencedTaskRunner::GetCurrentDefault()` to
345     // `task_runner` within its scope. `task_runner` must belong to the current
346     // sequence. There must not already be a current default
347     // `SequencedTaskRunner` on this thread.
348     explicit CurrentDefaultHandle(
349         scoped_refptr<SequencedTaskRunner> task_runner);
350 
351     CurrentDefaultHandle(const CurrentDefaultHandle&) = delete;
352     CurrentDefaultHandle& operator=(const CurrentDefaultHandle&) = delete;
353 
354     ~CurrentDefaultHandle();
355 
356    private:
357     friend class SequencedTaskRunner;
358 
359     // Overriding an existing current default SingleThreadTaskRunner should only
360     // be needed under special circumstances. Require them to be enumerated as
361     // friends to require //base/OWNERS review. Use
362     // SingleThreadTaskRunner::CurrentHandleOverrideForTesting in unit tests to
363     // avoid the friend requirement.
364     friend class SingleThreadTaskRunner;
365     FRIEND_TEST_ALL_PREFIXES(SequencedTaskRunnerCurrentDefaultHandleTest,
366                              OverrideWithNull);
367     FRIEND_TEST_ALL_PREFIXES(SequencedTaskRunnerCurrentDefaultHandleTest,
368                              OverrideWithNonNull);
369 
370     struct MayAlreadyExist {};
371 
372     // Same as the public constructor, but there may already be a current
373     // default `SequencedTaskRunner` on this thread.
374     CurrentDefaultHandle(scoped_refptr<SequencedTaskRunner> task_runner,
375                          MayAlreadyExist);
376 
377     scoped_refptr<SequencedTaskRunner> task_runner_;
378     // RAW_PTR_EXCLUSION: Performance reasons (based on analysis of
379     // speedometer3).
380     RAW_PTR_EXCLUSION CurrentDefaultHandle* previous_handle_ = nullptr;
381   };
382 
383  protected:
384   ~SequencedTaskRunner() override = default;
385 
386   virtual bool DeleteOrReleaseSoonInternal(const Location& from_here,
387                                            void (*deleter)(const void*),
388                                            const void* object);
389 };
390 
391 // Sample usage with std::unique_ptr :
392 // std::unique_ptr<Foo, base::OnTaskRunnerDeleter> ptr(
393 //     new Foo, base::OnTaskRunnerDeleter(my_task_runner));
394 //
395 // For RefCounted see base::RefCountedDeleteOnSequence.
396 struct BASE_EXPORT OnTaskRunnerDeleter {
397   explicit OnTaskRunnerDeleter(scoped_refptr<SequencedTaskRunner> task_runner);
398   ~OnTaskRunnerDeleter();
399 
400   OnTaskRunnerDeleter(OnTaskRunnerDeleter&&);
401   OnTaskRunnerDeleter& operator=(OnTaskRunnerDeleter&&);
402 
403   // For compatibility with std:: deleters.
404   template <typename T>
operatorOnTaskRunnerDeleter405   void operator()(const T* ptr) {
406     if (ptr)
407       task_runner_->DeleteSoon(FROM_HERE, ptr);
408   }
409 
410   scoped_refptr<SequencedTaskRunner> task_runner_;
411 };
412 
413 }  // namespace base
414 
415 #endif  // BASE_TASK_SEQUENCED_TASK_RUNNER_H_
416