Reland "Use std::atomic in Cancelable"
This is a reland of 61d42c9451
.
Switched to acquire/release memory order.
Original change's description:
> Use std::atomic in Cancelable
>
> Avoid deprecated base::AtomicValue, use std::atomic instead.
> Plus minor drive-by cleanups.
>
> R=mstarzinger@chromium.org
>
> Bug: v8:8238
> Change-Id: I47a1f00e26a843b60380c50399eedc49d859830a
> Reviewed-on: https://chromium-review.googlesource.com/c/1326463
> Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#57386}
Bug: v8:8238
Change-Id: I992a49d29af68cfa45bfae1bfb8dba5b47f94b25
Cq-Include-Trybots: luci.v8.try:v8_linux64_tsan_rel
Cq-Include-Trybots: luci.v8.try:v8_linux64_tsan_isolates_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/c/1329164
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57394}
This commit is contained in:
parent
a522da3935
commit
cc43dc974e
@ -10,18 +10,12 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
|
||||
Cancelable::Cancelable(CancelableTaskManager* parent)
|
||||
: parent_(parent), status_(kWaiting), id_(0), cancel_counter_(0) {
|
||||
id_ = parent->Register(this);
|
||||
}
|
||||
|
||||
|
||||
Cancelable::~Cancelable() {
|
||||
// The following check is needed to avoid calling an already terminated
|
||||
// manager object. This happens when the manager cancels all pending tasks
|
||||
// in {CancelAndWait} only before destroying the manager object.
|
||||
if (TryRun() || IsRunning()) {
|
||||
Status previous;
|
||||
if (TryRun(&previous) || previous == kRunning) {
|
||||
parent_->RemoveFinishedTask(id_);
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,10 @@
|
||||
#ifndef V8_CANCELABLE_TASK_H_
|
||||
#define V8_CANCELABLE_TASK_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "include/v8-platform.h"
|
||||
#include "src/base/atomic-utils.h"
|
||||
#include "src/base/macros.h"
|
||||
#include "src/base/platform/condition-variable.h"
|
||||
#include "src/globals.h"
|
||||
@ -86,7 +86,9 @@ class V8_EXPORT_PRIVATE CancelableTaskManager {
|
||||
|
||||
class V8_EXPORT_PRIVATE Cancelable {
|
||||
public:
|
||||
explicit Cancelable(CancelableTaskManager* parent);
|
||||
explicit Cancelable(CancelableTaskManager* parent)
|
||||
: parent_(parent), id_(parent->Register(this)) {}
|
||||
|
||||
virtual ~Cancelable();
|
||||
|
||||
// Never invoke after handing over the task to the platform! The reason is
|
||||
@ -97,42 +99,48 @@ class V8_EXPORT_PRIVATE Cancelable {
|
||||
CancelableTaskManager::Id id() { return id_; }
|
||||
|
||||
protected:
|
||||
bool TryRun() { return status_.TrySetValue(kWaiting, kRunning); }
|
||||
bool IsRunning() { return status_.Value() == kRunning; }
|
||||
intptr_t CancelAttempts() { return cancel_counter_; }
|
||||
|
||||
private:
|
||||
// Identifies the state a cancelable task is in:
|
||||
// |kWaiting|: The task is scheduled and waiting to be executed. {TryRun} will
|
||||
// succeed.
|
||||
// |kCanceled|: The task has been canceled. {TryRun} will fail.
|
||||
// |kRunning|: The task is currently running and cannot be canceled anymore.
|
||||
enum Status {
|
||||
kWaiting,
|
||||
kCanceled,
|
||||
kRunning,
|
||||
};
|
||||
enum Status { kWaiting, kCanceled, kRunning };
|
||||
|
||||
bool TryRun(Status* previous = nullptr) {
|
||||
return CompareExchangeStatus(kWaiting, kRunning, previous);
|
||||
}
|
||||
intptr_t CancelAttempts() { return cancel_counter_; }
|
||||
|
||||
private:
|
||||
friend class CancelableTaskManager;
|
||||
|
||||
// Use {CancelableTaskManager} to abort a task that has not yet been
|
||||
// executed.
|
||||
bool Cancel() {
|
||||
if (status_.TrySetValue(kWaiting, kCanceled)) {
|
||||
if (CompareExchangeStatus(kWaiting, kCanceled)) {
|
||||
return true;
|
||||
}
|
||||
cancel_counter_++;
|
||||
return false;
|
||||
}
|
||||
|
||||
CancelableTaskManager* parent_;
|
||||
base::AtomicValue<Status> status_;
|
||||
CancelableTaskManager::Id id_;
|
||||
bool CompareExchangeStatus(Status expected, Status desired,
|
||||
Status* previous = nullptr) {
|
||||
// {compare_exchange_strong} updates {expected}.
|
||||
bool success = status_.compare_exchange_strong(expected, desired,
|
||||
std::memory_order_acq_rel);
|
||||
if (previous) *previous = expected;
|
||||
return success;
|
||||
}
|
||||
|
||||
CancelableTaskManager* const parent_;
|
||||
std::atomic<Status> status_{kWaiting};
|
||||
const CancelableTaskManager::Id id_;
|
||||
|
||||
// The counter is incremented for failing tries to cancel a task. This can be
|
||||
// used by the task itself as an indication how often external entities tried
|
||||
// to abort it.
|
||||
std::atomic<intptr_t> cancel_counter_;
|
||||
|
||||
friend class CancelableTaskManager;
|
||||
std::atomic<intptr_t> cancel_counter_{0};
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Cancelable);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user