import Foundation class FIFO { typealias DataCallback = (String) -> () private var data = [String]() private var waitingDataList = [DataCallback]() private var syncQueue = DispatchQueue(label: "FIFO.sync") private var callBackQueue = DispatchQueue(label: "FIFO.callback", qos: .background, attributes: .concurrent) func isFreeable() -> Bool { return syncQueue.sync { waitingDataList.count == 0 && data.count == 0 } } func isDataAvailable() -> Bool { return syncQueue.sync { return data.count > 0 } } func enqueue(value: String) { syncQueue.sync { data.append(value) syncQueue.async { while self.waitingDataList.count > 0 { if self.data.count > 0 { let callback = self.waitingDataList.remove(at: 0) let val = self.data.remove(at: 0) self.callBackQueue.async { callback(val) } } else { return } } } } } func dequeue(onDataAvailable: @escaping DataCallback) { syncQueue.sync { if data.count > 0 { let val = data.remove(at: 0) callBackQueue.async { onDataAvailable(val) } } else { waitingDataList.append(onDataAvailable) } } } } let f = FIFO() var producerFinished = false print(" ******** START ******** ") DispatchQueue.global(qos: .background).async { for i in 1...100 { let ti = Double(arc4random_uniform(1000)) / Double(1000) Thread.sleep(forTimeInterval: ti) print("Producing: \(i)") f.enqueue(value: "product \(i)") } producerFinished = true } DispatchQueue.global(qos: .background).async { while !producerFinished || f.isDataAvailable() { let ti = Double(arc4random_uniform(1000)) / Double(1000) Thread.sleep(forTimeInterval: ti) f.dequeue { print("Consuming \($0)") } } } repeat { Thread.sleep(forTimeInterval: 3.0) } while !(f.isFreeable() && producerFinished) print(" ******** END ******** ")
giovedì 26 ottobre 2017
FIFO queue in Swift 4 with GCD
Iscriviti a:
Commenti sul post (Atom)
Nessun commento:
Posta un commento