import Foundation /// Cost-usage scans read and parse the full local session corpus synchronously and can run for /// minutes on large archives. Executing that work inline on Swift's cooperative thread pool /// starves every other async task in the process — menus freeze while the main thread sits idle — /// and overlapping provider scans multiply both the pool pressure and the disk load. This /// executor pins all corpus scans to a single serial utility queue off the cooperative pool, so /// long scans cost one dedicated thread instead of the app's async runtime. public enum CostUsageScanExecutor { public static let queueLabel = "com.steipete.codexbar.cost-usage-scan" private static let queue = DispatchQueue(label: queueLabel, qos: .utility) private final class RunState: @unchecked Sendable { private enum Phase { case initial case queued case running case completed } private let lock = NSLock() private var phase: Phase = .initial private var cancellationRequested = false private var continuation: CheckedContinuation? func install(_ continuation: CheckedContinuation) -> Bool { let shouldEnqueue: Bool let shouldResumeCancellation: Bool self.lock.lock() if self.cancellationRequested { self.phase = .completed shouldEnqueue = false shouldResumeCancellation = true } else { self.phase = .queued self.continuation = continuation shouldEnqueue = true shouldResumeCancellation = false } self.lock.unlock() if shouldResumeCancellation { continuation.resume(throwing: CancellationError()) } return shouldEnqueue } func begin() -> Bool { self.lock.lock() defer { self.lock.unlock() } guard self.phase == .queued else { return false } self.phase = .running return true } func cancel() { let continuation: CheckedContinuation? self.lock.lock() self.cancellationRequested = true if self.phase == .queued { self.phase = .completed continuation = self.continuation self.continuation = nil } else { continuation = nil } self.lock.unlock() continuation?.resume(throwing: CancellationError()) } func checkCancellation() throws { self.lock.lock() let cancellationRequested = self.cancellationRequested self.lock.unlock() if cancellationRequested { throw CancellationError() } } func complete(with result: Result) { let continuation: CheckedContinuation? let resolvedResult: Result self.lock.lock() guard self.phase == .running else { self.lock.unlock() return } self.phase = .completed continuation = self.continuation self.continuation = nil resolvedResult = self.cancellationRequested ? .failure(CancellationError()) : result self.lock.unlock() continuation?.resume(with: resolvedResult) } } /// Runs `work` on the serial scan queue and bridges Swift task cancellation into the /// scanner's cooperative `checkCancellation` callbacks. Work that is still queued when the /// awaiting task is cancelled resumes immediately with `CancellationError` instead of /// waiting behind an in-flight scan. public static func run( _ work: @escaping @Sendable (_ checkCancellation: @escaping @Sendable () throws -> Void) throws -> T) async throws -> T { try await self.run(on: self.queue, work) } static func run( on queue: DispatchQueue, _ work: @escaping @Sendable (_ checkCancellation: @escaping @Sendable () throws -> Void) throws -> T) async throws -> T { let state = RunState() let checkCancellation: @Sendable () throws -> Void = { try state.checkCancellation() } return try await withTaskCancellationHandler { try await withCheckedThrowingContinuation { continuation in guard state.install(continuation) else { return } queue.async { guard state.begin() else { return } state.complete(with: Result { try work(checkCancellation) }) } } } onCancel: { state.cancel() } } }