v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
cancelable-task.h
Go to the documentation of this file.
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#ifndef V8_TASKS_CANCELABLE_TASK_H_
6#define V8_TASKS_CANCELABLE_TASK_H_
7
8#include <atomic>
9#include <unordered_map>
10
11#include "include/v8-platform.h"
12#include "src/base/macros.h"
14
15namespace v8 {
16namespace internal {
17
18class Cancelable;
19class Isolate;
20
21// The possible outcomes of trying to abort a job are:
22// (1) The task is already finished running or was canceled before and
23// thus has been removed from the manager.
24// (2) The task is currently running and cannot be canceled anymore.
25// (3) The task is not yet running (or finished) so it is canceled and
26// removed.
28
29// Keeps track of cancelable tasks. It is possible to register and remove tasks
30// from any fore- and background task/thread.
32 public:
33 using Id = uint64_t;
34 static constexpr Id kInvalidTaskId = 0;
35
37
41
42 // Registers a new cancelable {task}. Returns the unique {id} of the task that
43 // can be used to try to abort a task by calling {Abort}.
44 // If {Register} is called after {CancelAndWait}, then the task will be
45 // aborted immediately.
46 // {Register} should only be called by the thread which owns the
47 // {CancelableTaskManager}, or by a task which is managed by the
48 // {CancelableTaskManager}.
49 Id Register(Cancelable* task);
50
51 // Try to abort running a task identified by {id}.
52 TryAbortResult TryAbort(Id id);
53
54 // Tries to cancel all remaining registered tasks. The return value indicates
55 // whether
56 //
57 // 1) No tasks were registered (kTaskRemoved), or
58 //
59 // 2) There is at least one remaining task that couldn't be cancelled
60 // (kTaskRunning), or
61 //
62 // 3) All registered tasks were cancelled (kTaskAborted).
63 TryAbortResult TryAbortAll();
64
65 // Cancels all remaining registered tasks and waits for tasks that are
66 // already running. This disallows subsequent Register calls.
67 void CancelAndWait();
68
69 // Returns true of the task manager has been cancelled.
70 bool canceled() const { return canceled_; }
71
72 private:
73 // Only called by {Cancelable} destructor. The task is done with executing,
74 // but needs to be removed.
75 void RemoveFinishedTask(Id id);
76
77 // To mitigate the ABA problem, the api refers to tasks through an id.
79
80 // A set of cancelable tasks that are currently registered.
81 std::unordered_map<Id, Cancelable*> cancelable_tasks_;
82
83 // Mutex and condition variable enabling concurrent register and removing, as
84 // well as waiting for background tasks on {CancelAndWait}.
87
89
90 friend class Cancelable;
91};
92
94 public:
96 : parent_(parent), id_(parent->Register(this)) {}
97
98 virtual ~Cancelable();
99 Cancelable(const Cancelable&) = delete;
100 Cancelable& operator=(const Cancelable&) = delete;
101
102 // Never invoke after handing over the task to the platform! The reason is
103 // that {Cancelable} is used in combination with {v8::Task} and handed to
104 // a platform. This step transfers ownership to the platform, which destroys
105 // the task after running it. Since the exact time is not known, we cannot
106 // access the object after handing it to a platform.
108
109 protected:
110 // Identifies the state a cancelable task is in:
111 // |kWaiting|: The task is scheduled and waiting to be executed. {TryRun} will
112 // succeed.
113 // |kCanceled|: The task has been canceled. {TryRun} will fail.
114 // |kRunning|: The task is currently running and cannot be canceled anymore.
115 enum Status { kWaiting, kCanceled, kRunning };
116
117 bool TryRun(Status* previous = nullptr) {
118 return CompareExchangeStatus(kWaiting, kRunning, previous);
119 }
120
121 private:
123
124 // Use {CancelableTaskManager} to abort a task that has not yet been
125 // executed.
126 bool Cancel() { return CompareExchangeStatus(kWaiting, kCanceled); }
127
128 bool CompareExchangeStatus(Status expected, Status desired,
129 Status* previous = nullptr) {
130 // {compare_exchange_strong} updates {expected}.
131 bool success = status_.compare_exchange_strong(expected, desired,
132 std::memory_order_acq_rel,
133 std::memory_order_acquire);
134 if (previous) *previous = expected;
135 return success;
136 }
137
139 std::atomic<Status> status_{kWaiting};
141};
142
143// Multiple inheritance can be used because Task is a pure interface.
145 NON_EXPORTED_BASE(public Task) {
146 public:
147 explicit CancelableTask(Isolate* isolate);
148 explicit CancelableTask(CancelableTaskManager* manager);
151
152 // Task overrides.
153 void Run() final {
154 if (TryRun()) {
155 RunInternal();
156 }
157 }
158
159 virtual void RunInternal() = 0;
160};
161
162// Multiple inheritance can be used because IdleTask is a pure interface.
163class CancelableIdleTask : public Cancelable, public IdleTask {
164 public:
165 explicit CancelableIdleTask(Isolate* isolate);
166 explicit CancelableIdleTask(CancelableTaskManager* manager);
169
170 // IdleTask overrides.
171 void Run(double deadline_in_seconds) final {
172 if (TryRun()) {
173 RunInternal(deadline_in_seconds);
174 }
175 }
176
177 virtual void RunInternal(double deadline_in_seconds) = 0;
178};
179
180} // namespace internal
181} // namespace v8
182
183#endif // V8_TASKS_CANCELABLE_TASK_H_
CancelableIdleTask & operator=(const CancelableIdleTask &)=delete
CancelableIdleTask(const CancelableIdleTask &)=delete
virtual void RunInternal(double deadline_in_seconds)=0
void Run(double deadline_in_seconds) final
CancelableTaskManager & operator=(const CancelableTaskManager &)=delete
CancelableTaskManager(const CancelableTaskManager &)=delete
std::unordered_map< Id, Cancelable * > cancelable_tasks_
base::ConditionVariable cancelable_tasks_barrier_
CancelableTask(const CancelableTask &)=delete
virtual void RunInternal()=0
CancelableTask & operator=(const CancelableTask &)=delete
CancelableTaskManager::Id id()
Cancelable(const Cancelable &)=delete
Cancelable & operator=(const Cancelable &)=delete
bool CompareExchangeStatus(Status expected, Status desired, Status *previous=nullptr)
const CancelableTaskManager::Id id_
CancelableTaskManager *const parent_
bool TryRun(Status *previous=nullptr)
Cancelable(CancelableTaskManager *parent)
LineAndColumn previous
BytecodeSequenceNode * parent_
#define NON_EXPORTED_BASE(code)
#define V8_EXPORT_PRIVATE
Definition macros.h:460