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

78 lines
1.5 KiB
Dart

import 'dart:async' as async;
class RuntimeSerialQueue<T> {
RuntimeSerialQueue({required this.onItem, bool Function()? shouldContinue})
: _shouldContinue = shouldContinue;
final void Function(T item) onItem;
final bool Function()? _shouldContinue;
final List<T> _queue = [];
int _head = 0;
bool _disposed = false;
bool _draining = false;
int get pendingCount => _queue.length - _head;
bool get isDraining => _draining;
bool get isDisposed => _disposed;
void enqueue(T item) {
if (_disposed || !_canContinue()) {
return;
}
_queue.add(item);
_scheduleDrain();
}
void clear() {
_queue.clear();
_head = 0;
}
void dispose() {
_disposed = true;
clear();
}
void _scheduleDrain() {
if (_draining) {
return;
}
_draining = true;
async.scheduleMicrotask(_drain);
}
void _drain() {
try {
while (pendingCount > 0 && !_disposed && _canContinue()) {
onItem(_queue[_head++]);
_compactIfNeeded();
}
} finally {
_draining = false;
}
if (pendingCount > 0 && !_disposed && _canContinue()) {
_scheduleDrain();
}
}
void _compactIfNeeded() {
if (_head == 0) {
return;
}
if (_head == _queue.length) {
clear();
return;
}
if (_head < 32 || _head * 2 < _queue.length) {
return;
}
_queue.removeRange(0, _head);
_head = 0;
}
bool _canContinue() => _shouldContinue?.call() ?? true;
}