// // DirectorThreadSafeClosures.swift // SwiftAudioPlayer // // Created by Tanha Kabir on 2019-01-29. // Copyright © 2019 Tanha Kabir, Jon Mercer // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import Foundation enum DirectorError: Error { case closureIsDead } /** P for payload */ class DirectorThreadSafeClosuresDeprecated
{ typealias TypeClosure = (Key, P) throws -> Void private var queue: DispatchQueue = DispatchQueue(label: "SwiftAudioPlayer.thread_safe_map", attributes: .concurrent) private var closures: [UInt: TypeClosure] = [:] private var cache: [Key: P] = [:] var count: Int { get { return closures.count } } func broadcast(key: Key, payload: P) { queue.sync { self.cache[key] = payload var iterator = self.closures.makeIterator() while let element = iterator.next() { do { try element.value(key, payload) } catch { helperRemove(withKey: element.key) } } } } //UInt is actually 64-bits on modern devices func attach(closure: @escaping TypeClosure) -> UInt { let id: UInt = Date.getUTC64() //The director may not yet have the status yet. We should only call the closure if we have it //Let the caller know the immediate value. If it's dead already then stop for (key, val) in cache { do { try closure(key, val) } catch { return id } } //Replace what's in the map with the new closure helperInsert(withKey: id, closure: closure) return id } func detach(id: UInt) { helperRemove(withKey: id) } func clear() { queue.async(flags: .barrier) { self.closures.removeAll() self.cache.removeAll() } } private func helperRemove(withKey key: UInt) { queue.async(flags: .barrier) { self.closures[key] = nil } } private func helperInsert(withKey key: UInt, closure: @escaping TypeClosure) { queue.async(flags: .barrier) { self.closures[key] = closure } } }