Swift3でCountdownLatchを作る、あるいはSemaphoreのtimeoutをSwift3で書く
テストの都合でラッチが欲しかったので、GCDのSemaphoreのラッパークラスを書こうと思ったんですね。
それで、 https://github.com/zhuhaow/CountdownLatch を参考にすれば割と簡単では! と思ったんですが、GCDの記法がSwift3で変わりすぎていて死ぬかと思った。のでメモ。
// 参考元: https://github.com/zhuhaow/CountdownLatch import Foundation class CountDownLatch { var count: Int private let dispatchQueue = DispatchQueue(label: "CountdownQueue") // 参考: https://qiita.com/codelynx/items/56ce2f91cd3f4f409aeb let semaphore = DispatchSemaphore(value: 0) let timeInSec : Int init?(count: Int, timeInSec: Int) { guard count > 0 else { return nil } self.count = count self.timeInSec = timeInSec } func countdown() { dispatchQueue.async { self.count -= 1 if self.count == 0 { self.semaphore.signal() } } } func await() -> Bool { // 参考: http://www.brilliantraven.com/code-snippets/grand-central-dispatch.html let result = semaphore.wait(timeout: DispatchTime.now() + DispatchTimeInterval.seconds(self.timeInSec)) if (result == .success) { return true } else { return false } } }
CouuntDownLatch
を使う側のコードは以下
func doTask() { let countDownLatch = CountDownLatch(count: 1, timeInSec: 30)! checkTimeoutBeforeCompletion(latch: countDownLatch) // なんか重い処理する countDownLatch.countdown() } func checkTimeoutBeforeCompletion(latch: CountDownLatch) { let queue = DispatchQueue(label: "background", attributes: .concurrent) queue.async { let processedOnTime = latch.await() if (processedOnTime) { NSLog("processed on time") } else { assertionFailure("遅いぞ!!!!") } } }