blob: 44448b15bc5d0c28408d0f806081bf9e9e402b83 [file] [log] [blame]
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
class CancelableToken extends CancellationToken {
bool _isCancelled = false;
@override
bool get isCancellationRequested => _isCancelled;
void cancel() => _isCancelled = true;
}
/// A token used to signal cancellation of an operation. This allows computation
/// to be skipped when a caller is no longer interested in the result, for example
/// when a $/cancel request is received for an in-progress request.
abstract class CancellationToken {
bool get isCancellationRequested;
}
/// A [CancellationToken] that cannot be cancelled.
class NotCancelableToken extends CancellationToken {
@override
bool get isCancellationRequested => false;
}
/// A cancellable wrapper over another cancellation token.
///
/// This token will be considered cancelled if either it is itself cancelled,
/// or if [child] is cancelled.
///
/// Cancelling this token will also cancel [child] if it is a cancelable
/// token.
class _WrappedCancelableToken extends CancelableToken {
final CancellationToken _child;
_WrappedCancelableToken(this._child);
@override
bool get isCancellationRequested =>
super.isCancellationRequested || _child.isCancellationRequested;
@override
void cancel() {
super.cancel();
final child = _child;
if (child is CancelableToken) {
child.cancel();
}
}
}
extension CancellationTokenExtension on CancellationToken {
/// Wraps this token to make it cancelable if it is not already.
CancelableToken asCancelable() {
final token = this;
return token is CancelableToken ? token : _WrappedCancelableToken(token);
}
}