xref: /aosp_15_r20/external/libchrome/base/task/cancelable_task_tracker.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2014 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 // CancelableTaskTracker posts tasks (in the form of a Closure) to a
6*635a8641SAndroid Build Coastguard Worker // TaskRunner, and is able to cancel the task later if it's not needed
7*635a8641SAndroid Build Coastguard Worker // anymore.  On destruction, CancelableTaskTracker will cancel all
8*635a8641SAndroid Build Coastguard Worker // tracked tasks.
9*635a8641SAndroid Build Coastguard Worker //
10*635a8641SAndroid Build Coastguard Worker // Each cancelable task can be associated with a reply (also a Closure). After
11*635a8641SAndroid Build Coastguard Worker // the task is run on the TaskRunner, |reply| will be posted back to
12*635a8641SAndroid Build Coastguard Worker // originating TaskRunner.
13*635a8641SAndroid Build Coastguard Worker //
14*635a8641SAndroid Build Coastguard Worker // NOTE:
15*635a8641SAndroid Build Coastguard Worker //
16*635a8641SAndroid Build Coastguard Worker // CancelableCallback (base/cancelable_callback.h) and WeakPtr binding are
17*635a8641SAndroid Build Coastguard Worker // preferred solutions for canceling a task. However, they don't support
18*635a8641SAndroid Build Coastguard Worker // cancelation from another sequence. This is sometimes a performance critical
19*635a8641SAndroid Build Coastguard Worker // requirement. E.g. We need to cancel database lookup task on DB thread when
20*635a8641SAndroid Build Coastguard Worker // user changes inputed text. If it is performance critical to do a best effort
21*635a8641SAndroid Build Coastguard Worker // cancelation of a task, then CancelableTaskTracker is appropriate, otherwise
22*635a8641SAndroid Build Coastguard Worker // use one of the other mechanisms.
23*635a8641SAndroid Build Coastguard Worker //
24*635a8641SAndroid Build Coastguard Worker // THREAD-SAFETY:
25*635a8641SAndroid Build Coastguard Worker //
26*635a8641SAndroid Build Coastguard Worker // 1. A CancelableTaskTracker object must be created, used, and destroyed on a
27*635a8641SAndroid Build Coastguard Worker //    single sequence.
28*635a8641SAndroid Build Coastguard Worker //
29*635a8641SAndroid Build Coastguard Worker // 2. It's safe to destroy a CancelableTaskTracker while there are outstanding
30*635a8641SAndroid Build Coastguard Worker //    tasks. This is commonly used to cancel all outstanding tasks.
31*635a8641SAndroid Build Coastguard Worker //
32*635a8641SAndroid Build Coastguard Worker // 3. The task is deleted on the target sequence, and the reply are deleted on
33*635a8641SAndroid Build Coastguard Worker //    the originating sequence.
34*635a8641SAndroid Build Coastguard Worker //
35*635a8641SAndroid Build Coastguard Worker // 4. IsCanceledCallback can be run or deleted on any sequence.
36*635a8641SAndroid Build Coastguard Worker #ifndef BASE_TASK_CANCELABLE_TASK_TRACKER_H_
37*635a8641SAndroid Build Coastguard Worker #define BASE_TASK_CANCELABLE_TASK_TRACKER_H_
38*635a8641SAndroid Build Coastguard Worker 
39*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
40*635a8641SAndroid Build Coastguard Worker 
41*635a8641SAndroid Build Coastguard Worker #include <utility>
42*635a8641SAndroid Build Coastguard Worker 
43*635a8641SAndroid Build Coastguard Worker #include "base/base_export.h"
44*635a8641SAndroid Build Coastguard Worker #include "base/bind.h"
45*635a8641SAndroid Build Coastguard Worker #include "base/callback.h"
46*635a8641SAndroid Build Coastguard Worker #include "base/containers/small_map.h"
47*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
48*635a8641SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h"
49*635a8641SAndroid Build Coastguard Worker #include "base/post_task_and_reply_with_result_internal.h"
50*635a8641SAndroid Build Coastguard Worker #include "base/sequence_checker.h"
51*635a8641SAndroid Build Coastguard Worker 
52*635a8641SAndroid Build Coastguard Worker namespace base {
53*635a8641SAndroid Build Coastguard Worker 
54*635a8641SAndroid Build Coastguard Worker class CancellationFlag;
55*635a8641SAndroid Build Coastguard Worker class Location;
56*635a8641SAndroid Build Coastguard Worker class TaskRunner;
57*635a8641SAndroid Build Coastguard Worker 
58*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT CancelableTaskTracker {
59*635a8641SAndroid Build Coastguard Worker  public:
60*635a8641SAndroid Build Coastguard Worker   // All values except kBadTaskId are valid.
61*635a8641SAndroid Build Coastguard Worker   typedef int64_t TaskId;
62*635a8641SAndroid Build Coastguard Worker   static const TaskId kBadTaskId;
63*635a8641SAndroid Build Coastguard Worker 
64*635a8641SAndroid Build Coastguard Worker   typedef Callback<bool()> IsCanceledCallback;
65*635a8641SAndroid Build Coastguard Worker 
66*635a8641SAndroid Build Coastguard Worker   CancelableTaskTracker();
67*635a8641SAndroid Build Coastguard Worker 
68*635a8641SAndroid Build Coastguard Worker   // Cancels all tracked tasks.
69*635a8641SAndroid Build Coastguard Worker   ~CancelableTaskTracker();
70*635a8641SAndroid Build Coastguard Worker 
71*635a8641SAndroid Build Coastguard Worker   TaskId PostTask(TaskRunner* task_runner,
72*635a8641SAndroid Build Coastguard Worker                   const Location& from_here,
73*635a8641SAndroid Build Coastguard Worker                   OnceClosure task);
74*635a8641SAndroid Build Coastguard Worker 
75*635a8641SAndroid Build Coastguard Worker   TaskId PostTaskAndReply(TaskRunner* task_runner,
76*635a8641SAndroid Build Coastguard Worker                           const Location& from_here,
77*635a8641SAndroid Build Coastguard Worker                           OnceClosure task,
78*635a8641SAndroid Build Coastguard Worker                           OnceClosure reply);
79*635a8641SAndroid Build Coastguard Worker 
80*635a8641SAndroid Build Coastguard Worker   template <typename TaskReturnType, typename ReplyArgType>
PostTaskAndReplyWithResult(TaskRunner * task_runner,const Location & from_here,OnceCallback<TaskReturnType ()> task,OnceCallback<void (ReplyArgType)> reply)81*635a8641SAndroid Build Coastguard Worker   TaskId PostTaskAndReplyWithResult(TaskRunner* task_runner,
82*635a8641SAndroid Build Coastguard Worker                                     const Location& from_here,
83*635a8641SAndroid Build Coastguard Worker                                     OnceCallback<TaskReturnType()> task,
84*635a8641SAndroid Build Coastguard Worker                                     OnceCallback<void(ReplyArgType)> reply) {
85*635a8641SAndroid Build Coastguard Worker     TaskReturnType* result = new TaskReturnType();
86*635a8641SAndroid Build Coastguard Worker     return PostTaskAndReply(
87*635a8641SAndroid Build Coastguard Worker         task_runner, from_here,
88*635a8641SAndroid Build Coastguard Worker         BindOnce(&internal::ReturnAsParamAdapter<TaskReturnType>,
89*635a8641SAndroid Build Coastguard Worker                  std::move(task), Unretained(result)),
90*635a8641SAndroid Build Coastguard Worker         BindOnce(&internal::ReplyAdapter<TaskReturnType, ReplyArgType>,
91*635a8641SAndroid Build Coastguard Worker                  std::move(reply), Owned(result)));
92*635a8641SAndroid Build Coastguard Worker   }
93*635a8641SAndroid Build Coastguard Worker 
94*635a8641SAndroid Build Coastguard Worker   // Callback version of PostTaskWithTraitsAndReplyWithResult above.
95*635a8641SAndroid Build Coastguard Worker   // Though RepeatingCallback is convertible to OnceCallback, we need this since
96*635a8641SAndroid Build Coastguard Worker   // we can not use template deduction and object conversion at once on the
97*635a8641SAndroid Build Coastguard Worker   // overload resolution.
98*635a8641SAndroid Build Coastguard Worker   // TODO(tzik): Update all callers of the Callback version to use OnceCallback.
99*635a8641SAndroid Build Coastguard Worker   template <typename TaskReturnType, typename ReplyArgType>
PostTaskAndReplyWithResult(TaskRunner * task_runner,const Location & from_here,Callback<TaskReturnType ()> task,Callback<void (ReplyArgType)> reply)100*635a8641SAndroid Build Coastguard Worker   TaskId PostTaskAndReplyWithResult(TaskRunner* task_runner,
101*635a8641SAndroid Build Coastguard Worker                                     const Location& from_here,
102*635a8641SAndroid Build Coastguard Worker                                     Callback<TaskReturnType()> task,
103*635a8641SAndroid Build Coastguard Worker                                     Callback<void(ReplyArgType)> reply) {
104*635a8641SAndroid Build Coastguard Worker     return PostTaskAndReplyWithResult(
105*635a8641SAndroid Build Coastguard Worker         task_runner, from_here,
106*635a8641SAndroid Build Coastguard Worker         static_cast<OnceCallback<TaskReturnType()>>(std::move(task)),
107*635a8641SAndroid Build Coastguard Worker         static_cast<OnceCallback<void(ReplyArgType)>>(std::move(reply)));
108*635a8641SAndroid Build Coastguard Worker   }
109*635a8641SAndroid Build Coastguard Worker 
110*635a8641SAndroid Build Coastguard Worker   // Creates a tracked TaskId and an associated IsCanceledCallback. Client can
111*635a8641SAndroid Build Coastguard Worker   // later call TryCancel() with the returned TaskId, and run |is_canceled_cb|
112*635a8641SAndroid Build Coastguard Worker   // from any thread to check whether the TaskId is canceled.
113*635a8641SAndroid Build Coastguard Worker   //
114*635a8641SAndroid Build Coastguard Worker   // The returned task ID is tracked until the last copy of
115*635a8641SAndroid Build Coastguard Worker   // |is_canceled_cb| is destroyed.
116*635a8641SAndroid Build Coastguard Worker   //
117*635a8641SAndroid Build Coastguard Worker   // Note. This function is used to address some special cancelation requirement
118*635a8641SAndroid Build Coastguard Worker   // in existing code. You SHOULD NOT need this function in new code.
119*635a8641SAndroid Build Coastguard Worker   TaskId NewTrackedTaskId(IsCanceledCallback* is_canceled_cb);
120*635a8641SAndroid Build Coastguard Worker 
121*635a8641SAndroid Build Coastguard Worker   // After calling this function, |task| and |reply| will not run. If the
122*635a8641SAndroid Build Coastguard Worker   // cancelation happens when |task| is running or has finished running, |reply|
123*635a8641SAndroid Build Coastguard Worker   // will not run. If |reply| is running or has finished running, cancellation
124*635a8641SAndroid Build Coastguard Worker   // is a noop.
125*635a8641SAndroid Build Coastguard Worker   //
126*635a8641SAndroid Build Coastguard Worker   // Note. It's OK to cancel a |task| for more than once. The later calls are
127*635a8641SAndroid Build Coastguard Worker   // noops.
128*635a8641SAndroid Build Coastguard Worker   void TryCancel(TaskId id);
129*635a8641SAndroid Build Coastguard Worker 
130*635a8641SAndroid Build Coastguard Worker   // It's OK to call this function for more than once. The later calls are
131*635a8641SAndroid Build Coastguard Worker   // noops.
132*635a8641SAndroid Build Coastguard Worker   void TryCancelAll();
133*635a8641SAndroid Build Coastguard Worker 
134*635a8641SAndroid Build Coastguard Worker   // Returns true iff there are in-flight tasks that are still being
135*635a8641SAndroid Build Coastguard Worker   // tracked.
136*635a8641SAndroid Build Coastguard Worker   bool HasTrackedTasks() const;
137*635a8641SAndroid Build Coastguard Worker 
138*635a8641SAndroid Build Coastguard Worker  private:
139*635a8641SAndroid Build Coastguard Worker   void Track(TaskId id, CancellationFlag* flag);
140*635a8641SAndroid Build Coastguard Worker   void Untrack(TaskId id);
141*635a8641SAndroid Build Coastguard Worker 
142*635a8641SAndroid Build Coastguard Worker   // Typically the number of tasks are 0-2 and occationally 3-4. But since
143*635a8641SAndroid Build Coastguard Worker   // this is a general API that could be used in unexpected ways, use a
144*635a8641SAndroid Build Coastguard Worker   // small_map instead of a flat_map to avoid falling over if there are many
145*635a8641SAndroid Build Coastguard Worker   // tasks.
146*635a8641SAndroid Build Coastguard Worker   small_map<std::map<TaskId, CancellationFlag*>, 4> task_flags_;
147*635a8641SAndroid Build Coastguard Worker 
148*635a8641SAndroid Build Coastguard Worker   TaskId next_id_;
149*635a8641SAndroid Build Coastguard Worker   SequenceChecker sequence_checker_;
150*635a8641SAndroid Build Coastguard Worker 
151*635a8641SAndroid Build Coastguard Worker   WeakPtrFactory<CancelableTaskTracker> weak_factory_;
152*635a8641SAndroid Build Coastguard Worker 
153*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(CancelableTaskTracker);
154*635a8641SAndroid Build Coastguard Worker };
155*635a8641SAndroid Build Coastguard Worker 
156*635a8641SAndroid Build Coastguard Worker }  // namespace base
157*635a8641SAndroid Build Coastguard Worker 
158*635a8641SAndroid Build Coastguard Worker #endif  // BASE_TASK_CANCELABLE_TASK_TRACKER_H_
159