import 'dart:async' as async; class RuntimeSerialQueue { RuntimeSerialQueue({required this.onItem, bool Function()? shouldContinue}) : _shouldContinue = shouldContinue; final void Function(T item) onItem; final bool Function()? _shouldContinue; final List _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; }