Thanks to visit codestin.com
Credit goes to chromium.googlesource.com

blob: 7abc57aa12e2b8d782ea4999b5589386e907e1a0 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2014 The Chromium Authors
[email protected]62867b02012-11-03 07:21:032// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
kylechar01598d72019-05-21 18:35:315// CancelableTaskTracker posts tasks (in the form of a OnceClosure) to a
[email protected]e95b717f2014-02-06 13:47:136// TaskRunner, and is able to cancel the task later if it's not needed
7// anymore. On destruction, CancelableTaskTracker will cancel all
8// tracked tasks.
[email protected]62867b02012-11-03 07:21:039//
kylechar01598d72019-05-21 18:35:3110// Each cancelable task can be associated with a reply (also a OnceClosure).
11// After the task is run on the TaskRunner, |reply| will be posted back to
[email protected]e95b717f2014-02-06 13:47:1312// originating TaskRunner.
[email protected]62867b02012-11-03 07:21:0313//
14// NOTE:
15//
Colin Blundellea615d422021-05-12 09:35:4116// CancelableOnceCallback (base/cancelable_callback.h) and WeakPtr binding are
[email protected]62867b02012-11-03 07:21:0317// preferred solutions for canceling a task. However, they don't support
fdoray6661c522016-12-21 13:02:0818// cancelation from another sequence. This is sometimes a performance critical
[email protected]62867b02012-11-03 07:21:0319// requirement. E.g. We need to cancel database lookup task on DB thread when
Colin Blundellea615d422021-05-12 09:35:4120// user changes inputted text. If it is performance critical to do a best effort
fdoray6661c522016-12-21 13:02:0821// cancelation of a task, then CancelableTaskTracker is appropriate, otherwise
22// use one of the other mechanisms.
[email protected]62867b02012-11-03 07:21:0323//
24// THREAD-SAFETY:
25//
fdoray6661c522016-12-21 13:02:0826// 1. A CancelableTaskTracker object must be created, used, and destroyed on a
27// single sequence.
[email protected]62867b02012-11-03 07:21:0328//
fdoray6661c522016-12-21 13:02:0829// 2. It's safe to destroy a CancelableTaskTracker while there are outstanding
30// tasks. This is commonly used to cancel all outstanding tasks.
[email protected]4f1935e2012-11-16 23:10:0731//
tzikd773cb472017-04-17 18:58:1932// 3. The task is deleted on the target sequence, and the reply are deleted on
33// the originating sequence.
fdoray6661c522016-12-21 13:02:0834//
35// 4. IsCanceledCallback can be run or deleted on any sequence.
[email protected]e95b717f2014-02-06 13:47:1336#ifndef BASE_TASK_CANCELABLE_TASK_TRACKER_H_
37#define BASE_TASK_CANCELABLE_TASK_TRACKER_H_
[email protected]62867b02012-11-03 07:21:0338
avi9b6f42932015-12-26 22:15:1439#include <stdint.h>
40
Mikel Astizc076a972018-07-25 13:49:2541#include <memory>
tzik03527512017-02-08 12:29:4742#include <utility>
43
[email protected]e95b717f2014-02-06 13:47:1344#include "base/base_export.h"
brettw1ce49f62017-04-27 19:42:3245#include "base/containers/small_map.h"
Avi Drissman63e1f992023-01-13 18:54:4346#include "base/functional/bind.h"
47#include "base/functional/callback.h"
48#include "base/functional/callback_helpers.h"
Wez77d9d102019-01-10 00:20:2149#include "base/memory/ref_counted.h"
Wez50cbb922019-12-05 20:40:4150#include "base/memory/weak_ptr.h"
fdoray6661c522016-12-21 13:02:0851#include "base/sequence_checker.h"
Wez77d9d102019-01-10 00:20:2152#include "base/synchronization/atomic_flag.h"
Patrick Monette643cdf62021-10-15 19:13:4253#include "base/task/post_task_and_reply_with_result_internal.h"
[email protected]62867b02012-11-03 07:21:0354
[email protected]e95b717f2014-02-06 13:47:1355namespace base {
56
Brett Wilsonabbb9602017-09-11 23:26:3957class Location;
Wez77d9d102019-01-10 00:20:2158class ScopedClosureRunner;
[email protected]e95b717f2014-02-06 13:47:1359class TaskRunner;
60
61class BASE_EXPORT CancelableTaskTracker {
[email protected]62867b02012-11-03 07:21:0362 public:
63 // All values except kBadTaskId are valid.
avi9b6f42932015-12-26 22:15:1464 typedef int64_t TaskId;
[email protected]62867b02012-11-03 07:21:0365 static const TaskId kBadTaskId;
66
kylechar01598d72019-05-21 18:35:3167 using IsCanceledCallback = RepeatingCallback<bool()>;
[email protected]4f1935e2012-11-16 23:10:0768
[email protected]62867b02012-11-03 07:21:0369 CancelableTaskTracker();
70
Peter Boström7319bbd2021-09-15 22:59:3871 CancelableTaskTracker(const CancelableTaskTracker&) = delete;
72 CancelableTaskTracker& operator=(const CancelableTaskTracker&) = delete;
73
[email protected]62867b02012-11-03 07:21:0374 // Cancels all tracked tasks.
75 ~CancelableTaskTracker();
76
tzikd773cb472017-04-17 18:58:1977 TaskId PostTask(TaskRunner* task_runner,
Brett Wilsonabbb9602017-09-11 23:26:3978 const Location& from_here,
tzikd773cb472017-04-17 18:58:1979 OnceClosure task);
[email protected]62867b02012-11-03 07:21:0380
tzikd773cb472017-04-17 18:58:1981 TaskId PostTaskAndReply(TaskRunner* task_runner,
Brett Wilsonabbb9602017-09-11 23:26:3982 const Location& from_here,
tzikd773cb472017-04-17 18:58:1983 OnceClosure task,
84 OnceClosure reply);
[email protected]62867b02012-11-03 07:21:0385
Jan Wilken Dörrie2e1d2d9a2020-01-24 17:14:1886 template <typename TaskReturnType, typename ReplyArgType>
tzikd773cb472017-04-17 18:58:1987 TaskId PostTaskAndReplyWithResult(TaskRunner* task_runner,
Brett Wilsonabbb9602017-09-11 23:26:3988 const Location& from_here,
Jan Wilken Dörrie2e1d2d9a2020-01-24 17:14:1889 OnceCallback<TaskReturnType()> task,
90 OnceCallback<void(ReplyArgType)> reply) {
Mikel Astizc076a972018-07-25 13:49:2591 auto* result = new std::unique_ptr<TaskReturnType>();
[email protected]f5449ac2014-07-04 11:19:5092 return PostTaskAndReply(
tzik03527512017-02-08 12:29:4793 task_runner, from_here,
tzikd773cb472017-04-17 18:58:1994 BindOnce(&internal::ReturnAsParamAdapter<TaskReturnType>,
95 std::move(task), Unretained(result)),
96 BindOnce(&internal::ReplyAdapter<TaskReturnType, ReplyArgType>,
97 std::move(reply), Owned(result)));
98 }
99
[email protected]4f1935e2012-11-16 23:10:07100 // Creates a tracked TaskId and an associated IsCanceledCallback. Client can
101 // later call TryCancel() with the returned TaskId, and run |is_canceled_cb|
[email protected]d5dd90d2012-11-26 21:13:35102 // from any thread to check whether the TaskId is canceled.
[email protected]4f1935e2012-11-16 23:10:07103 //
[email protected]3d5b88a2012-11-28 23:28:45104 // The returned task ID is tracked until the last copy of
105 // |is_canceled_cb| is destroyed.
106 //
[email protected]4f1935e2012-11-16 23:10:07107 // Note. This function is used to address some special cancelation requirement
108 // in existing code. You SHOULD NOT need this function in new code.
109 TaskId NewTrackedTaskId(IsCanceledCallback* is_canceled_cb);
110
[email protected]62867b02012-11-03 07:21:03111 // After calling this function, |task| and |reply| will not run. If the
112 // cancelation happens when |task| is running or has finished running, |reply|
113 // will not run. If |reply| is running or has finished running, cancellation
114 // is a noop.
115 //
116 // Note. It's OK to cancel a |task| for more than once. The later calls are
117 // noops.
118 void TryCancel(TaskId id);
119
120 // It's OK to call this function for more than once. The later calls are
121 // noops.
122 void TryCancelAll();
123
[email protected]3d5b88a2012-11-28 23:28:45124 // Returns true iff there are in-flight tasks that are still being
125 // tracked.
126 bool HasTrackedTasks() const;
127
[email protected]62867b02012-11-03 07:21:03128 private:
Wez77d9d102019-01-10 00:20:21129 // Cancellation flags are ref-counted to ensure they remain valid even if the
130 // tracker and its calling thread are torn down while there are still
131 // cancelable tasks queued to the target TaskRunner.
132 // See https://crbug.com/918948.
133 using TaskCancellationFlag = RefCountedData<AtomicFlag>;
134
Wezd6a5f0f22023-04-14 14:28:48135 static void RunIfNotCanceled(const scoped_refptr<TaskCancellationFlag>& flag,
136 OnceClosure task);
Wezc9bba142019-11-15 07:36:46137 static void RunThenUntrackIfNotCanceled(
138 const scoped_refptr<TaskCancellationFlag>& flag,
139 OnceClosure task,
140 OnceClosure untrack);
Wezd6a5f0f22023-04-14 14:28:48141 static bool IsCanceled(const scoped_refptr<TaskCancellationFlag>& flag,
142 const ScopedClosureRunner& cleanup_runner);
Wez77d9d102019-01-10 00:20:21143
144 void Track(TaskId id, scoped_refptr<TaskCancellationFlag> flag);
[email protected]62867b02012-11-03 07:21:03145 void Untrack(TaskId id);
146
brettw1ce49f62017-04-27 19:42:32147 // Typically the number of tasks are 0-2 and occationally 3-4. But since
148 // this is a general API that could be used in unexpected ways, use a
149 // small_map instead of a flat_map to avoid falling over if there are many
150 // tasks.
Wez77d9d102019-01-10 00:20:21151 small_map<std::map<TaskId, scoped_refptr<TaskCancellationFlag>>, 4>
152 task_flags_;
[email protected]62867b02012-11-03 07:21:03153
Wez77d9d102019-01-10 00:20:21154 TaskId next_id_ = 1;
Christian Flach3eee7702022-09-09 14:25:43155 SEQUENCE_CHECKER(sequence_checker_);
[email protected]62867b02012-11-03 07:21:03156
Alison Gale59c007a2024-04-20 03:05:40157 // TODO(crbug.com/40050290): Remove once crasher is resolved.
Wez50cbb922019-12-05 20:40:41158 base::WeakPtr<CancelableTaskTracker> weak_this_;
159 base::WeakPtrFactory<CancelableTaskTracker> weak_factory_{this};
[email protected]62867b02012-11-03 07:21:03160};
161
[email protected]e95b717f2014-02-06 13:47:13162} // namespace base
163
164#endif // BASE_TASK_CANCELABLE_TASK_TRACKER_H_