RadrootsTransferCallbackQueue.swift (1409B)
1 import Foundation 2 3 /// Delegate callbacks arrive on a serial OS queue. Preserve that order across 4 /// Swift suspension so finished events cannot overtake receipt persistence. 5 final class RadrootsTransferCallbackQueue: @unchecked Sendable { 6 private let lock = NSLock() 7 private var tail: Task<Void, Never>? 8 private var receipts: [RadrootsBackgroundTransferIdentifier: Int] = [:] 9 10 var pendingIdentifiers: Set<RadrootsBackgroundTransferIdentifier> { 11 lock.withLock { Set(receipts.keys) } 12 } 13 14 func enqueue( 15 receipt identifier: RadrootsBackgroundTransferIdentifier? = nil, 16 operation: @escaping @Sendable () async -> Void 17 ) { 18 lock.withLock { 19 if let identifier { 20 receipts[identifier, default: 0] += 1 21 } 22 let previous = tail 23 tail = Task { 24 await previous?.value 25 await operation() 26 if let identifier { 27 self.finished(identifier) 28 } 29 } 30 } 31 } 32 33 private func finished(_ identifier: RadrootsBackgroundTransferIdentifier) { 34 lock.withLock { 35 let remaining = (receipts[identifier] ?? 1) - 1 36 if remaining == 0 { 37 receipts.removeValue(forKey: identifier) 38 } else { 39 receipts[identifier] = remaining 40 } 41 } 42 } 43 }