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

147 lines
3.4 KiB
Dart

class RuntimeCommandRegistry {
final Set<RuntimeCommandHandle> _handles = {};
final Map<String, Set<RuntimeCommandHandle>> _handlesById = {};
final Map<String, Set<RuntimeCommandHandle>> _handlesByGroup = {};
final Map<String, Set<RuntimeCommandHandle>> _handlesByScope = {};
bool _disposed = false;
int get activeHandleCount => _handles.length;
RuntimeCommandHandle create({String? id, String? group, String? scope}) {
if (_disposed) {
throw StateError('RuntimeCommandRegistry has been disposed');
}
late final RuntimeCommandHandle handle;
handle = RuntimeCommandHandle._(
id: id,
group: group,
scope: scope,
onComplete: _unregister,
);
_handles.add(handle);
_index(_handlesById, id, handle);
_index(_handlesByGroup, group, handle);
_index(_handlesByScope, scope, handle);
return handle;
}
void cancelId(String id) {
_cancelAll(_handlesById[id]);
}
void cancelGroup(String group) {
_cancelAll(_handlesByGroup[group]);
}
void cancelScope(String scope) {
_cancelAll(_handlesByScope[scope]);
}
void dispose() {
if (_disposed) {
return;
}
_disposed = true;
_cancelAll(_handles);
_handles.clear();
_handlesById.clear();
_handlesByGroup.clear();
_handlesByScope.clear();
}
void _index(
Map<String, Set<RuntimeCommandHandle>> index,
String? key,
RuntimeCommandHandle handle,
) {
if (key == null) {
return;
}
index.putIfAbsent(key, () => {}).add(handle);
}
void _cancelAll(Set<RuntimeCommandHandle>? handles) {
final snapshot = handles?.toList(growable: false) ?? const [];
for (final handle in snapshot) {
handle.cancel();
}
}
void _unregister(RuntimeCommandHandle handle) {
_handles.remove(handle);
_unindex(_handlesById, handle.id, handle);
_unindex(_handlesByGroup, handle.group, handle);
_unindex(_handlesByScope, handle.scope, handle);
}
void _unindex(
Map<String, Set<RuntimeCommandHandle>> index,
String? key,
RuntimeCommandHandle handle,
) {
if (key == null) {
return;
}
final handles = index[key];
handles?.remove(handle);
if (handles != null && handles.isEmpty) {
index.remove(key);
}
}
}
class RuntimeCommandHandle {
RuntimeCommandHandle._({
required this.id,
required this.group,
required this.scope,
required void Function(RuntimeCommandHandle handle) onComplete,
}) : _onComplete = onComplete;
final String? id;
final String? group;
final String? scope;
final void Function(RuntimeCommandHandle handle) _onComplete;
final List<void Function()> _cancelCallbacks = [];
bool _cancelled = false;
bool _completed = false;
bool get isCancelled => _cancelled;
bool get isCompleted => _completed;
void addCancelCallback(void Function() callback) {
if (_cancelled) {
callback();
return;
}
if (_completed) {
return;
}
_cancelCallbacks.add(callback);
}
void complete() {
if (_completed) {
return;
}
_completed = true;
_cancelCallbacks.clear();
_onComplete(this);
}
void cancel() {
if (_cancelled || _completed) {
return;
}
_cancelled = true;
final callbacks = _cancelCallbacks.toList(growable: false);
_cancelCallbacks.clear();
for (final callback in callbacks) {
callback();
}
complete();
}
}