Files
flutter_lua_runtime/lib/runtime/lifecycle/runtime_task_registry.dart
2026-06-07 22:53:58 +08:00

130 lines
2.9 KiB
Dart

import 'dart:async' as async;
class RuntimeTaskRegistry<T> {
RuntimeTaskRegistry({required this.cancelledValue});
final T cancelledValue;
final Set<RuntimeTask<T>> _tasks = {};
final Map<String, Set<RuntimeTask<T>>> _tasksByScope = {};
bool _disposed = false;
int get activeTaskCount => _tasks.length;
int scopedTaskCount(String scope) => _tasksByScope[scope]?.length ?? 0;
RuntimeTask<T> create({String? scope}) {
if (_disposed) {
throw StateError('RuntimeTaskRegistry has been disposed');
}
late final RuntimeTask<T> task;
task = RuntimeTask<T>._(
scope: scope,
cancelledValue: cancelledValue,
onComplete: _unregister,
);
_tasks.add(task);
if (scope != null) {
_tasksByScope.putIfAbsent(scope, () => {}).add(task);
}
return task;
}
void cancelScope(String scope) {
final tasks = _tasksByScope[scope]?.toList(growable: false) ?? const [];
for (final task in tasks) {
task.cancel();
}
}
void dispose() {
if (_disposed) {
return;
}
_disposed = true;
final tasks = _tasks.toList(growable: false);
for (final task in tasks) {
task.cancel();
}
_tasks.clear();
_tasksByScope.clear();
}
void _unregister(RuntimeTask<T> task) {
_tasks.remove(task);
final scope = task.scope;
if (scope == null) {
return;
}
final scopedTasks = _tasksByScope[scope];
scopedTasks?.remove(task);
if (scopedTasks != null && scopedTasks.isEmpty) {
_tasksByScope.remove(scope);
}
}
}
class RuntimeTask<T> {
RuntimeTask._({
required this.scope,
required this.cancelledValue,
required void Function(RuntimeTask<T> task) onComplete,
}) : _onComplete = onComplete;
final String? scope;
final T cancelledValue;
final void Function(RuntimeTask<T> task) _onComplete;
final async.Completer<T> _completer = async.Completer<T>();
final Set<async.Timer> _timers = {};
final List<void Function()> _cancelCallbacks = [];
bool _cancelled = false;
Future<T> get future => _completer.future;
bool get isCancelled => _cancelled;
void addTimer(async.Timer timer) {
if (_cancelled) {
timer.cancel();
return;
}
_timers.add(timer);
}
void removeTimer(async.Timer timer) {
_timers.remove(timer);
}
void addCancelCallback(void Function() callback) {
if (_cancelled) {
callback();
return;
}
_cancelCallbacks.add(callback);
}
void complete(T result) {
if (_completer.isCompleted) {
return;
}
_completer.complete(result);
_onComplete(this);
}
void cancel() {
if (_cancelled) {
return;
}
_cancelled = true;
for (final timer in _timers) {
timer.cancel();
}
_timers.clear();
for (final callback in _cancelCallbacks) {
callback();
}
_cancelCallbacks.clear();
complete(cancelledValue);
}
}