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