blob: a8e19204ef53e73332ff850414378eac62aa5cac [file] [log] [blame]
// Copyright (c) 2015, 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.
import 'dart:async';
import 'sync_errors.dart';
/// Used by classes which may be terminated from the outside.
mixin TerminatableMixin {
bool _terminated = false;
/// Terminates this stream message queue. Further operations on it will fail.
void terminate([Object? error]) {
if (!wasTerminated) {
_terminated = true;
onTerminated(error);
}
}
bool get wasTerminated => _terminated;
void onTerminated(Object? error) {
// Subclasses can override this method if they want.
}
T ensureNotTerminatedSync<T>(T Function() f) {
if (wasTerminated) {
throw TerminatedException();
}
return f();
}
Future ensureNotTerminatedAsync(Future Function() f) {
if (wasTerminated) {
return Future.error(TerminatedException());
}
return f();
}
}
/// Used by classes which may be cancelled.
mixin CancellableMixin {
bool _cancelled = false;
final _cancelCompleter = Completer<void>.sync();
Future<void> get onCancel => _cancelCompleter.future;
/// Cancel this stream message queue. Further operations on it will fail.
void cancel() {
if (!wasCancelled) {
_cancelled = true;
_cancelCompleter.complete();
}
}
bool get wasCancelled => _cancelled;
}
/// Used by classes which may be closed.
mixin ClosableMixin {
bool _closing = false;
final Completer _completer = Completer<void>();
Future get done => _completer.future;
bool get isClosing => _closing;
bool get wasClosed => _completer.isCompleted;
void startClosing() {
if (!_closing) {
_closing = true;
onClosing();
}
onCheckForClose();
}
void onCheckForClose() {
// Subclasses can override this method if they want.
}
void onClosing() {
// Subclasses can override this method if they want.
}
dynamic ensureNotClosingSync(dynamic Function() f) {
if (isClosing) {
throw StateError('Was in the process of closing.');
}
return f();
}
void closeWithValue([Object? value]) {
if (!wasClosed) {
_completer.complete(value);
}
}
void closeWithError(Object? error) {
if (!wasClosed) {
_completer.complete(error);
}
}
}