Initial flame_lua_runtime package
This commit is contained in:
129
lib/runtime/lifecycle/runtime_task_registry.dart
Normal file
129
lib/runtime/lifecycle/runtime_task_registry.dart
Normal file
@@ -0,0 +1,129 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user