TeraLifecycleBridge.swift (1416B)
1 import Foundation 2 3 final class TeraCompletionOnce: @unchecked Sendable { 4 private let lock = NSLock() 5 private var completion: (() -> Void)? 6 7 init(_ completion: @escaping () -> Void) { 8 self.completion = completion 9 } 10 11 func complete() { 12 let action = lock.withLock { 13 let action = completion 14 completion = nil 15 return action 16 } 17 action?() 18 } 19 } 20 21 actor TeraLifecycleBridge { 22 static let shared = TeraLifecycleBridge() 23 24 private var registration = UUID() 25 private var shutdown: (@Sendable () async -> Bool)? 26 private struct Attempt { 27 let id: UUID 28 let registration: UUID 29 let task: Task<Bool, Never> 30 } 31 32 private var active: Attempt? 33 34 func register(shutdown: @escaping @Sendable () async -> Bool) { 35 registration = UUID() 36 self.shutdown = shutdown 37 } 38 39 func requestShutdown() async { 40 let id = registration 41 let attempt: Attempt 42 if let active, active.registration == id { 43 attempt = active 44 } else if let shutdown { 45 attempt = Attempt(id: UUID(), registration: id, task: Task { await shutdown() }) 46 active = attempt 47 } else { 48 return 49 } 50 let completed = await attempt.task.value 51 if active?.id == attempt.id { 52 active = nil 53 } 54 if registration == id, completed { 55 shutdown = nil 56 } 57 if registration == id { 58 await TeraBackgroundEventRouter.shared.detachAndCompletePending() 59 } 60 } 61 }