xref: /aosp_15_r20/external/libchrome/base/sequenced_task_runner.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #ifndef BASE_SEQUENCED_TASK_RUNNER_H_
6*635a8641SAndroid Build Coastguard Worker #define BASE_SEQUENCED_TASK_RUNNER_H_
7*635a8641SAndroid Build Coastguard Worker 
8*635a8641SAndroid Build Coastguard Worker #include <memory>
9*635a8641SAndroid Build Coastguard Worker 
10*635a8641SAndroid Build Coastguard Worker #include "base/base_export.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/callback.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/sequenced_task_runner_helpers.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/task_runner.h"
14*635a8641SAndroid Build Coastguard Worker 
15*635a8641SAndroid Build Coastguard Worker namespace base {
16*635a8641SAndroid Build Coastguard Worker 
17*635a8641SAndroid Build Coastguard Worker // A SequencedTaskRunner is a subclass of TaskRunner that provides
18*635a8641SAndroid Build Coastguard Worker // additional guarantees on the order that tasks are started, as well
19*635a8641SAndroid Build Coastguard Worker // as guarantees on when tasks are in sequence, i.e. one task finishes
20*635a8641SAndroid Build Coastguard Worker // before the other one starts.
21*635a8641SAndroid Build Coastguard Worker //
22*635a8641SAndroid Build Coastguard Worker // Summary
23*635a8641SAndroid Build Coastguard Worker // -------
24*635a8641SAndroid Build Coastguard Worker // Non-nested tasks with the same delay will run one by one in FIFO
25*635a8641SAndroid Build Coastguard Worker // order.
26*635a8641SAndroid Build Coastguard Worker //
27*635a8641SAndroid Build Coastguard Worker // Detailed guarantees
28*635a8641SAndroid Build Coastguard Worker // -------------------
29*635a8641SAndroid Build Coastguard Worker //
30*635a8641SAndroid Build Coastguard Worker // SequencedTaskRunner also adds additional methods for posting
31*635a8641SAndroid Build Coastguard Worker // non-nestable tasks.  In general, an implementation of TaskRunner
32*635a8641SAndroid Build Coastguard Worker // may expose task-running methods which are themselves callable from
33*635a8641SAndroid Build Coastguard Worker // within tasks.  A non-nestable task is one that is guaranteed to not
34*635a8641SAndroid Build Coastguard Worker // be run from within an already-running task.  Conversely, a nestable
35*635a8641SAndroid Build Coastguard Worker // task (the default) is a task that can be run from within an
36*635a8641SAndroid Build Coastguard Worker // already-running task.
37*635a8641SAndroid Build Coastguard Worker //
38*635a8641SAndroid Build Coastguard Worker // The guarantees of SequencedTaskRunner are as follows:
39*635a8641SAndroid Build Coastguard Worker //
40*635a8641SAndroid Build Coastguard Worker //   - Given two tasks T2 and T1, T2 will start after T1 starts if:
41*635a8641SAndroid Build Coastguard Worker //
42*635a8641SAndroid Build Coastguard Worker //       * T2 is posted after T1; and
43*635a8641SAndroid Build Coastguard Worker //       * T2 has equal or higher delay than T1; and
44*635a8641SAndroid Build Coastguard Worker //       * T2 is non-nestable or T1 is nestable.
45*635a8641SAndroid Build Coastguard Worker //
46*635a8641SAndroid Build Coastguard Worker //   - If T2 will start after T1 starts by the above guarantee, then
47*635a8641SAndroid Build Coastguard Worker //     T2 will start after T1 finishes and is destroyed if:
48*635a8641SAndroid Build Coastguard Worker //
49*635a8641SAndroid Build Coastguard Worker //       * T2 is non-nestable, or
50*635a8641SAndroid Build Coastguard Worker //       * T1 doesn't call any task-running methods.
51*635a8641SAndroid Build Coastguard Worker //
52*635a8641SAndroid Build Coastguard Worker //   - If T2 will start after T1 finishes by the above guarantee, then
53*635a8641SAndroid Build Coastguard Worker //     all memory changes in T1 and T1's destruction will be visible
54*635a8641SAndroid Build Coastguard Worker //     to T2.
55*635a8641SAndroid Build Coastguard Worker //
56*635a8641SAndroid Build Coastguard Worker //   - If T2 runs nested within T1 via a call to the task-running
57*635a8641SAndroid Build Coastguard Worker //     method M, then all memory changes in T1 up to the call to M
58*635a8641SAndroid Build Coastguard Worker //     will be visible to T2, and all memory changes in T2 will be
59*635a8641SAndroid Build Coastguard Worker //     visible to T1 from the return from M.
60*635a8641SAndroid Build Coastguard Worker //
61*635a8641SAndroid Build Coastguard Worker // Note that SequencedTaskRunner does not guarantee that tasks are run
62*635a8641SAndroid Build Coastguard Worker // on a single dedicated thread, although the above guarantees provide
63*635a8641SAndroid Build Coastguard Worker // most (but not all) of the same guarantees.  If you do need to
64*635a8641SAndroid Build Coastguard Worker // guarantee that tasks are run on a single dedicated thread, see
65*635a8641SAndroid Build Coastguard Worker // SingleThreadTaskRunner (in single_thread_task_runner.h).
66*635a8641SAndroid Build Coastguard Worker //
67*635a8641SAndroid Build Coastguard Worker // Some corollaries to the above guarantees, assuming the tasks in
68*635a8641SAndroid Build Coastguard Worker // question don't call any task-running methods:
69*635a8641SAndroid Build Coastguard Worker //
70*635a8641SAndroid Build Coastguard Worker //   - Tasks posted via PostTask are run in FIFO order.
71*635a8641SAndroid Build Coastguard Worker //
72*635a8641SAndroid Build Coastguard Worker //   - Tasks posted via PostNonNestableTask are run in FIFO order.
73*635a8641SAndroid Build Coastguard Worker //
74*635a8641SAndroid Build Coastguard Worker //   - Tasks posted with the same delay and the same nestable state
75*635a8641SAndroid Build Coastguard Worker //     are run in FIFO order.
76*635a8641SAndroid Build Coastguard Worker //
77*635a8641SAndroid Build Coastguard Worker //   - A list of tasks with the same nestable state posted in order of
78*635a8641SAndroid Build Coastguard Worker //     non-decreasing delay is run in FIFO order.
79*635a8641SAndroid Build Coastguard Worker //
80*635a8641SAndroid Build Coastguard Worker //   - A list of tasks posted in order of non-decreasing delay with at
81*635a8641SAndroid Build Coastguard Worker //     most a single change in nestable state from nestable to
82*635a8641SAndroid Build Coastguard Worker //     non-nestable is run in FIFO order. (This is equivalent to the
83*635a8641SAndroid Build Coastguard Worker //     statement of the first guarantee above.)
84*635a8641SAndroid Build Coastguard Worker //
85*635a8641SAndroid Build Coastguard Worker // Some theoretical implementations of SequencedTaskRunner:
86*635a8641SAndroid Build Coastguard Worker //
87*635a8641SAndroid Build Coastguard Worker //   - A SequencedTaskRunner that wraps a regular TaskRunner but makes
88*635a8641SAndroid Build Coastguard Worker //     sure that only one task at a time is posted to the TaskRunner,
89*635a8641SAndroid Build Coastguard Worker //     with appropriate memory barriers in between tasks.
90*635a8641SAndroid Build Coastguard Worker //
91*635a8641SAndroid Build Coastguard Worker //   - A SequencedTaskRunner that, for each task, spawns a joinable
92*635a8641SAndroid Build Coastguard Worker //     thread to run that task and immediately quit, and then
93*635a8641SAndroid Build Coastguard Worker //     immediately joins that thread.
94*635a8641SAndroid Build Coastguard Worker //
95*635a8641SAndroid Build Coastguard Worker //   - A SequencedTaskRunner that stores the list of posted tasks and
96*635a8641SAndroid Build Coastguard Worker //     has a method Run() that runs each runnable task in FIFO order
97*635a8641SAndroid Build Coastguard Worker //     that can be called from any thread, but only if another
98*635a8641SAndroid Build Coastguard Worker //     (non-nested) Run() call isn't already happening.
99*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT SequencedTaskRunner : public TaskRunner {
100*635a8641SAndroid Build Coastguard Worker  public:
101*635a8641SAndroid Build Coastguard Worker   // The two PostNonNestable*Task methods below are like their
102*635a8641SAndroid Build Coastguard Worker   // nestable equivalents in TaskRunner, but they guarantee that the
103*635a8641SAndroid Build Coastguard Worker   // posted task will not run nested within an already-running task.
104*635a8641SAndroid Build Coastguard Worker   //
105*635a8641SAndroid Build Coastguard Worker   // A simple corollary is that posting a task as non-nestable can
106*635a8641SAndroid Build Coastguard Worker   // only delay when the task gets run.  That is, posting a task as
107*635a8641SAndroid Build Coastguard Worker   // non-nestable may not affect when the task gets run, or it could
108*635a8641SAndroid Build Coastguard Worker   // make it run later than it normally would, but it won't make it
109*635a8641SAndroid Build Coastguard Worker   // run earlier than it normally would.
110*635a8641SAndroid Build Coastguard Worker 
111*635a8641SAndroid Build Coastguard Worker   // TODO(akalin): Get rid of the boolean return value for the methods
112*635a8641SAndroid Build Coastguard Worker   // below.
113*635a8641SAndroid Build Coastguard Worker 
114*635a8641SAndroid Build Coastguard Worker   bool PostNonNestableTask(const Location& from_here, OnceClosure task);
115*635a8641SAndroid Build Coastguard Worker 
116*635a8641SAndroid Build Coastguard Worker   virtual bool PostNonNestableDelayedTask(const Location& from_here,
117*635a8641SAndroid Build Coastguard Worker                                           OnceClosure task,
118*635a8641SAndroid Build Coastguard Worker                                           base::TimeDelta delay) = 0;
119*635a8641SAndroid Build Coastguard Worker 
120*635a8641SAndroid Build Coastguard Worker   // Submits a non-nestable task to delete the given object.  Returns
121*635a8641SAndroid Build Coastguard Worker   // true if the object may be deleted at some point in the future,
122*635a8641SAndroid Build Coastguard Worker   // and false if the object definitely will not be deleted.
123*635a8641SAndroid Build Coastguard Worker   template <class T>
DeleteSoon(const Location & from_here,const T * object)124*635a8641SAndroid Build Coastguard Worker   bool DeleteSoon(const Location& from_here, const T* object) {
125*635a8641SAndroid Build Coastguard Worker     return DeleteOrReleaseSoonInternal(from_here, &DeleteHelper<T>::DoDelete,
126*635a8641SAndroid Build Coastguard Worker                                        object);
127*635a8641SAndroid Build Coastguard Worker   }
128*635a8641SAndroid Build Coastguard Worker 
129*635a8641SAndroid Build Coastguard Worker   template <class T>
DeleteSoon(const Location & from_here,std::unique_ptr<T> object)130*635a8641SAndroid Build Coastguard Worker   bool DeleteSoon(const Location& from_here, std::unique_ptr<T> object) {
131*635a8641SAndroid Build Coastguard Worker     return DeleteSoon(from_here, object.release());
132*635a8641SAndroid Build Coastguard Worker   }
133*635a8641SAndroid Build Coastguard Worker 
134*635a8641SAndroid Build Coastguard Worker   // Submits a non-nestable task to release the given object.  Returns
135*635a8641SAndroid Build Coastguard Worker   // true if the object may be released at some point in the future,
136*635a8641SAndroid Build Coastguard Worker   // and false if the object definitely will not be released.
137*635a8641SAndroid Build Coastguard Worker   template <class T>
ReleaseSoon(const Location & from_here,const T * object)138*635a8641SAndroid Build Coastguard Worker   bool ReleaseSoon(const Location& from_here, const T* object) {
139*635a8641SAndroid Build Coastguard Worker     return DeleteOrReleaseSoonInternal(from_here, &ReleaseHelper<T>::DoRelease,
140*635a8641SAndroid Build Coastguard Worker                                        object);
141*635a8641SAndroid Build Coastguard Worker   }
142*635a8641SAndroid Build Coastguard Worker 
143*635a8641SAndroid Build Coastguard Worker  protected:
144*635a8641SAndroid Build Coastguard Worker   ~SequencedTaskRunner() override = default;
145*635a8641SAndroid Build Coastguard Worker 
146*635a8641SAndroid Build Coastguard Worker  private:
147*635a8641SAndroid Build Coastguard Worker   bool DeleteOrReleaseSoonInternal(const Location& from_here,
148*635a8641SAndroid Build Coastguard Worker                                    void (*deleter)(const void*),
149*635a8641SAndroid Build Coastguard Worker                                    const void* object);
150*635a8641SAndroid Build Coastguard Worker };
151*635a8641SAndroid Build Coastguard Worker 
152*635a8641SAndroid Build Coastguard Worker // Sample usage with std::unique_ptr :
153*635a8641SAndroid Build Coastguard Worker // std::unique_ptr<Foo, base::OnTaskRunnerDeleter> ptr(
154*635a8641SAndroid Build Coastguard Worker //     new Foo, base::OnTaskRunnerDeleter(my_task_runner));
155*635a8641SAndroid Build Coastguard Worker //
156*635a8641SAndroid Build Coastguard Worker // For RefCounted see base::RefCountedDeleteOnSequence.
157*635a8641SAndroid Build Coastguard Worker struct BASE_EXPORT OnTaskRunnerDeleter {
158*635a8641SAndroid Build Coastguard Worker   explicit OnTaskRunnerDeleter(scoped_refptr<SequencedTaskRunner> task_runner);
159*635a8641SAndroid Build Coastguard Worker   ~OnTaskRunnerDeleter();
160*635a8641SAndroid Build Coastguard Worker 
161*635a8641SAndroid Build Coastguard Worker   OnTaskRunnerDeleter(OnTaskRunnerDeleter&&);
162*635a8641SAndroid Build Coastguard Worker   OnTaskRunnerDeleter& operator=(OnTaskRunnerDeleter&&);
163*635a8641SAndroid Build Coastguard Worker 
164*635a8641SAndroid Build Coastguard Worker   // For compatibility with std:: deleters.
165*635a8641SAndroid Build Coastguard Worker   template <typename T>
operatorOnTaskRunnerDeleter166*635a8641SAndroid Build Coastguard Worker   void operator()(const T* ptr) {
167*635a8641SAndroid Build Coastguard Worker     if (ptr)
168*635a8641SAndroid Build Coastguard Worker       task_runner_->DeleteSoon(FROM_HERE, ptr);
169*635a8641SAndroid Build Coastguard Worker   }
170*635a8641SAndroid Build Coastguard Worker 
171*635a8641SAndroid Build Coastguard Worker   scoped_refptr<SequencedTaskRunner> task_runner_;
172*635a8641SAndroid Build Coastguard Worker };
173*635a8641SAndroid Build Coastguard Worker 
174*635a8641SAndroid Build Coastguard Worker }  // namespace base
175*635a8641SAndroid Build Coastguard Worker 
176*635a8641SAndroid Build Coastguard Worker #endif  // BASE_SEQUENCED_TASK_RUNNER_H_
177