| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/common/cancelable_task_tracker.h" | 5 #include "chrome/common/cancelable_task_tracker.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "base/location.h" |
| 11 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 12 #include "base/message_loop_proxy.h" | 13 #include "base/message_loop_proxy.h" |
| 13 #include "base/synchronization/cancellation_flag.h" | 14 #include "base/synchronization/cancellation_flag.h" |
| 14 #include "base/task_runner.h" | 15 #include "base/task_runner.h" |
| 15 | 16 |
| 16 using base::Bind; | 17 using base::Bind; |
| 17 using base::CancellationFlag; | 18 using base::CancellationFlag; |
| 18 using base::Closure; | 19 using base::Closure; |
| 19 using base::hash_map; | 20 using base::hash_map; |
| 20 using base::TaskRunner; | 21 using base::TaskRunner; |
| 21 | 22 |
| 22 namespace { | 23 namespace { |
| 23 | 24 |
| 24 void RunIfNotCanceled(const CancellationFlag* flag, const Closure& task) { | 25 void RunIfNotCanceled(const CancellationFlag* flag, const Closure& task) { |
| 25 if (!flag->IsSet()) | 26 if (!flag->IsSet()) |
| 26 task.Run(); | 27 task.Run(); |
| 27 } | 28 } |
| 28 | 29 |
| 29 void RunIfNotCanceledThenUntrack(const CancellationFlag* flag, | 30 void RunIfNotCanceledThenUntrack(const CancellationFlag* flag, |
| 30 const Closure& task, | 31 const Closure& task, |
| 31 const Closure& untrack) { | 32 const Closure& untrack) { |
| 32 RunIfNotCanceled(flag, task); | 33 RunIfNotCanceled(flag, task); |
| 33 untrack.Run(); | 34 untrack.Run(); |
| 34 } | 35 } |
| 35 | 36 |
| 37 bool IsCanceled(const CancellationFlag* flag, |
| 38 base::ScopedClosureRunner* cleanup_runner) { |
| 39 return flag->IsSet(); |
| 40 } |
| 41 |
| 42 void RunAndDeleteFlag(const Closure& closure, const CancellationFlag* flag) { |
| 43 closure.Run(); |
| 44 delete flag; |
| 45 } |
| 46 |
| 47 void RunOrPostToTaskRunner(TaskRunner* task_runner, const Closure& closure) { |
| 48 if (task_runner->RunsTasksOnCurrentThread()) |
| 49 closure.Run(); |
| 50 else |
| 51 task_runner->PostTask(FROM_HERE, closure); |
| 52 } |
| 53 |
| 36 } // namespace | 54 } // namespace |
| 37 | 55 |
| 38 // static | 56 // static |
| 39 const CancelableTaskTracker::TaskId CancelableTaskTracker::kBadTaskId = 0; | 57 const CancelableTaskTracker::TaskId CancelableTaskTracker::kBadTaskId = 0; |
| 40 | 58 |
| 41 CancelableTaskTracker::CancelableTaskTracker() | 59 CancelableTaskTracker::CancelableTaskTracker() |
| 42 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 60 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| 43 next_id_(1) {} | 61 next_id_(1) {} |
| 44 | 62 |
| 45 CancelableTaskTracker::~CancelableTaskTracker() { | 63 CancelableTaskTracker::~CancelableTaskTracker() { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 Bind(&RunIfNotCanceledThenUntrack, | 95 Bind(&RunIfNotCanceledThenUntrack, |
| 78 base::Owned(flag), reply, untrack_closure)); | 96 base::Owned(flag), reply, untrack_closure)); |
| 79 | 97 |
| 80 if (!success) | 98 if (!success) |
| 81 return kBadTaskId; | 99 return kBadTaskId; |
| 82 | 100 |
| 83 Track(id, flag); | 101 Track(id, flag); |
| 84 return id; | 102 return id; |
| 85 } | 103 } |
| 86 | 104 |
| 105 CancelableTaskTracker::TaskId CancelableTaskTracker::NewTrackedTaskId( |
| 106 IsCanceledCallback* is_canceled_cb) { |
| 107 DCHECK(thread_checker_.CalledOnValidThread()); |
| 108 DCHECK(base::MessageLoopProxy::current()); |
| 109 |
| 110 TaskId id = next_id_; |
| 111 next_id_++; // int64 is big enough that we ignore the potential overflow. |
| 112 |
| 113 // Will be deleted by |untrack_and_delete_flag| after Untrack(). |
| 114 CancellationFlag* flag = new CancellationFlag(); |
| 115 |
| 116 Closure untrack_and_delete_flag = Bind( |
| 117 &RunAndDeleteFlag, |
| 118 Bind(&CancelableTaskTracker::Untrack, weak_factory_.GetWeakPtr(), id), |
| 119 flag); |
| 120 |
| 121 // Will always run |untrack_and_delete_flag| on current MessageLoop. |
| 122 base::ScopedClosureRunner* untrack_and_delete_flag_runner = |
| 123 new base::ScopedClosureRunner( |
| 124 Bind(&RunOrPostToTaskRunner, |
| 125 base::MessageLoopProxy::current(), |
| 126 untrack_and_delete_flag)); |
| 127 |
| 128 *is_canceled_cb = Bind( |
| 129 &IsCanceled, flag, base::Owned(untrack_and_delete_flag_runner)); |
| 130 |
| 131 Track(id, flag); |
| 132 return id; |
| 133 } |
| 134 |
| 87 void CancelableTaskTracker::TryCancel(TaskId id) { | 135 void CancelableTaskTracker::TryCancel(TaskId id) { |
| 88 DCHECK(thread_checker_.CalledOnValidThread()); | 136 DCHECK(thread_checker_.CalledOnValidThread()); |
| 89 | 137 |
| 90 hash_map<TaskId, CancellationFlag*>::const_iterator it = task_flags_.find(id); | 138 hash_map<TaskId, CancellationFlag*>::const_iterator it = task_flags_.find(id); |
| 91 if (it == task_flags_.end()) { | 139 if (it == task_flags_.end()) { |
| 92 // 3 possibilities: | 140 // 3 possibilities: |
| 93 // 1. Task (and reply) has finished running. | 141 // 1. Task (and reply) has finished running. |
| 94 // 2. Task was canceled before and already untracked. | 142 // 2. Task was canceled before and already untracked. |
| 95 // 3. The TaskId is bad or never used. | 143 // 3. The TaskId is bad or never used. |
| 96 // Since we only try best to cancel task and reply, it's OK to ignore these. | 144 // Since we only try best to cancel task and reply, it's OK to ignore these. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 114 bool success = task_flags_.insert(std::make_pair(id, flag)).second; | 162 bool success = task_flags_.insert(std::make_pair(id, flag)).second; |
| 115 DCHECK(success); | 163 DCHECK(success); |
| 116 } | 164 } |
| 117 | 165 |
| 118 void CancelableTaskTracker::Untrack(TaskId id) { | 166 void CancelableTaskTracker::Untrack(TaskId id) { |
| 119 DCHECK(thread_checker_.CalledOnValidThread()); | 167 DCHECK(thread_checker_.CalledOnValidThread()); |
| 120 | 168 |
| 121 size_t num = task_flags_.erase(id); | 169 size_t num = task_flags_.erase(id); |
| 122 DCHECK_EQ(1u, num); | 170 DCHECK_EQ(1u, num); |
| 123 } | 171 } |
| OLD | NEW |