Line data Source code
1 : // Copyright 2015 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/cancelable-task.h"
6 :
7 : #include "src/base/platform/platform.h"
8 : #include "src/isolate.h"
9 :
10 : namespace v8 {
11 : namespace internal {
12 :
13 :
14 13 : Cancelable::Cancelable(CancelableTaskManager* parent)
15 2093344 : : parent_(parent), status_(kWaiting), id_(0), cancel_counter_(0) {
16 1046672 : id_ = parent->Register(this);
17 13 : }
18 :
19 :
20 1044591 : Cancelable::~Cancelable() {
21 : // The following check is needed to avoid calling an already terminated
22 : // manager object. This happens when the manager cancels all pending tasks
23 : // in {CancelAndWait} only before destroying the manager object.
24 1044591 : if (TryRun() || IsRunning()) {
25 1005900 : parent_->RemoveFinishedTask(id_);
26 : }
27 1046217 : }
28 :
29 264251 : CancelableTaskManager::CancelableTaskManager()
30 528502 : : task_id_counter_(0), canceled_(false) {}
31 :
32 1046672 : CancelableTaskManager::Id CancelableTaskManager::Register(Cancelable* task) {
33 1046672 : base::LockGuard<base::Mutex> guard(&mutex_);
34 1046671 : CancelableTaskManager::Id id = ++task_id_counter_;
35 : // Id overflows are not supported.
36 1046671 : CHECK_NE(0, id);
37 1046671 : CHECK(!canceled_);
38 1046671 : cancelable_tasks_[id] = task;
39 2093343 : return id;
40 : }
41 :
42 1005548 : void CancelableTaskManager::RemoveFinishedTask(CancelableTaskManager::Id id) {
43 1005548 : base::LockGuard<base::Mutex> guard(&mutex_);
44 : size_t removed = cancelable_tasks_.erase(id);
45 : USE(removed);
46 : DCHECK_NE(0u, removed);
47 1006194 : cancelable_tasks_barrier_.NotifyOne();
48 1006159 : }
49 :
50 581764 : CancelableTaskManager::TryAbortResult CancelableTaskManager::TryAbort(
51 : CancelableTaskManager::Id id) {
52 581764 : base::LockGuard<base::Mutex> guard(&mutex_);
53 : auto entry = cancelable_tasks_.find(id);
54 581764 : if (entry != cancelable_tasks_.end()) {
55 74834 : Cancelable* value = entry->second;
56 74834 : if (value->Cancel()) {
57 : // Cannot call RemoveFinishedTask here because of recursive locking.
58 : cancelable_tasks_.erase(entry);
59 37094 : cancelable_tasks_barrier_.NotifyOne();
60 37094 : return kTaskAborted;
61 : } else {
62 : return kTaskRunning;
63 : }
64 : }
65 : return kTaskRemoved;
66 : }
67 :
68 :
69 110952 : void CancelableTaskManager::CancelAndWait() {
70 : // Clean up all cancelable fore- and background tasks. Tasks are canceled on
71 : // the way if possible, i.e., if they have not started yet. After each round
72 : // of canceling we wait for the background tasks that have already been
73 : // started.
74 110952 : base::LockGuard<base::Mutex> guard(&mutex_);
75 110952 : canceled_ = true;
76 :
77 : // Cancelable tasks could be running or could potentially register new
78 : // tasks, requiring a loop here.
79 225609 : while (!cancelable_tasks_.empty()) {
80 16971 : for (auto it = cancelable_tasks_.begin(); it != cancelable_tasks_.end();) {
81 : auto current = it;
82 : // We need to get to the next element before erasing the current.
83 : ++it;
84 9561 : if (current->second->Cancel()) {
85 : cancelable_tasks_.erase(current);
86 : }
87 : }
88 : // Wait for already running background tasks.
89 3705 : if (!cancelable_tasks_.empty()) {
90 2370 : cancelable_tasks_barrier_.Wait(&mutex_);
91 : }
92 : }
93 110952 : }
94 :
95 106767 : CancelableTaskManager::TryAbortResult CancelableTaskManager::TryAbortAll() {
96 : // Clean up all cancelable fore- and background tasks. Tasks are canceled on
97 : // the way if possible, i.e., if they have not started yet.
98 106767 : base::LockGuard<base::Mutex> guard(&mutex_);
99 :
100 106767 : if (cancelable_tasks_.empty()) return kTaskRemoved;
101 :
102 54 : for (auto it = cancelable_tasks_.begin(); it != cancelable_tasks_.end();) {
103 20 : if (it->second->Cancel()) {
104 : it = cancelable_tasks_.erase(it);
105 : } else {
106 : ++it;
107 : }
108 : }
109 :
110 17 : return cancelable_tasks_.empty() ? kTaskAborted : kTaskRunning;
111 : }
112 :
113 1016210 : CancelableTask::CancelableTask(Isolate* isolate)
114 1016210 : : CancelableTask(isolate->cancelable_task_manager()) {}
115 :
116 1041043 : CancelableTask::CancelableTask(CancelableTaskManager* manager)
117 2082086 : : Cancelable(manager) {}
118 :
119 5589 : CancelableIdleTask::CancelableIdleTask(Isolate* isolate)
120 5589 : : CancelableIdleTask(isolate->cancelable_task_manager()) {}
121 :
122 5616 : CancelableIdleTask::CancelableIdleTask(CancelableTaskManager* manager)
123 11232 : : Cancelable(manager) {}
124 :
125 : } // namespace internal
126 : } // namespace v8
|