| 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* untrack_runner) { |
| 39 return flag->IsSet(); |
| 40 } |
| 41 |
| 42 void RunOrPostToTaskRunner(TaskRunner* task_runner, const Closure& closure) { |
| 43 if (task_runner->RunsTasksOnCurrentThread()) |
| 44 closure.Run(); |
| 45 else |
| 46 task_runner->PostTask(FROM_HERE, closure); |
| 47 } |
| 48 |
| 36 } // namespace | 49 } // namespace |
| 37 | 50 |
| 38 // static | 51 // static |
| 39 const CancelableTaskTracker::TaskId CancelableTaskTracker::kBadTaskId = 0; | 52 const CancelableTaskTracker::TaskId CancelableTaskTracker::kBadTaskId = 0; |
| 40 | 53 |
| 41 CancelableTaskTracker::CancelableTaskTracker() | 54 CancelableTaskTracker::CancelableTaskTracker() |
| 42 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 55 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| 43 next_id_(1) {} | 56 next_id_(1) {} |
| 44 | 57 |
| 45 CancelableTaskTracker::~CancelableTaskTracker() { | 58 CancelableTaskTracker::~CancelableTaskTracker() { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 Bind(&RunIfNotCanceledThenUntrack, | 90 Bind(&RunIfNotCanceledThenUntrack, |
| 78 base::Owned(flag), reply, untrack_closure)); | 91 base::Owned(flag), reply, untrack_closure)); |
| 79 | 92 |
| 80 if (!success) | 93 if (!success) |
| 81 return kBadTaskId; | 94 return kBadTaskId; |
| 82 | 95 |
| 83 Track(id, flag); | 96 Track(id, flag); |
| 84 return id; | 97 return id; |
| 85 } | 98 } |
| 86 | 99 |
| 100 CancelableTaskTracker::TaskId CancelableTaskTracker::NewTrackedTaskId( |
| 101 IsCanceledCallback* is_canceled_cb) { |
| 102 DCHECK(thread_checker_.CalledOnValidThread()); |
| 103 DCHECK(base::MessageLoopProxy::current()); |
| 104 |
| 105 TaskId id = next_id_; |
| 106 next_id_++; // int64 is big enough that we ignore the potential overflow. |
| 107 |
| 108 // Both owned by |is_canceled_cb|. |
| 109 CancellationFlag* flag = new CancellationFlag(); |
| 110 base::ScopedClosureRunner* untrack_runner = new base::ScopedClosureRunner( |
| 111 Bind(&RunOrPostToTaskRunner, |
| 112 base::MessageLoopProxy::current(), |
| 113 Bind(&CancelableTaskTracker::Untrack, |
| 114 weak_factory_.GetWeakPtr(), id))); |
| 115 |
| 116 *is_canceled_cb = Bind(&IsCanceled, |
| 117 base::Owned(flag), |
| 118 base::Owned(untrack_runner)); |
| 119 Track(id, flag); |
| 120 return id; |
| 121 } |
| 122 |
| 87 void CancelableTaskTracker::TryCancel(TaskId id) { | 123 void CancelableTaskTracker::TryCancel(TaskId id) { |
| 88 DCHECK(thread_checker_.CalledOnValidThread()); | 124 DCHECK(thread_checker_.CalledOnValidThread()); |
| 89 | 125 |
| 90 hash_map<TaskId, CancellationFlag*>::const_iterator it = task_flags_.find(id); | 126 hash_map<TaskId, CancellationFlag*>::const_iterator it = task_flags_.find(id); |
| 91 if (it == task_flags_.end()) { | 127 if (it == task_flags_.end()) { |
| 92 // 3 possibilities: | 128 // 3 possibilities: |
| 93 // 1. Task (and reply) has finished running. | 129 // 1. Task (and reply) has finished running. |
| 94 // 2. Task was canceled before and already untracked. | 130 // 2. Task was canceled before and already untracked. |
| 95 // 3. The TaskId is bad or never used. | 131 // 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. | 132 // 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; | 150 bool success = task_flags_.insert(std::make_pair(id, flag)).second; |
| 115 DCHECK(success); | 151 DCHECK(success); |
| 116 } | 152 } |
| 117 | 153 |
| 118 void CancelableTaskTracker::Untrack(TaskId id) { | 154 void CancelableTaskTracker::Untrack(TaskId id) { |
| 119 DCHECK(thread_checker_.CalledOnValidThread()); | 155 DCHECK(thread_checker_.CalledOnValidThread()); |
| 120 | 156 |
| 121 size_t num = task_flags_.erase(id); | 157 size_t num = task_flags_.erase(id); |
| 122 DCHECK_EQ(1u, num); | 158 DCHECK_EQ(1u, num); |
| 123 } | 159 } |
| OLD | NEW |