Skip to content

Instantly share code, notes, and snippets.

@smoofra
Last active August 9, 2022 14:50
Show Gist options
  • Save smoofra/86a9f50ee3734abbd317e90b441eea89 to your computer and use it in GitHub Desktop.
Save smoofra/86a9f50ee3734abbd317e90b441eea89 to your computer and use it in GitHub Desktop.
AsyncSemaphore
class AsyncSemaphore {
struct waiter {
var continuation: CheckedContinuation<Void,Never>
var next: UnsafeMutablePointer<waiter>?
}
var value : Int
var waitList : UnsafeMutablePointer<waiter>?
var lock = os_unfair_lock()
init(value: Int) {
self.value = value
}
func wait() async {
os_unfair_lock_lock(&self.lock)
if self.value > 0 {
self.value -= 1
os_unfair_lock_unlock(&self.lock)
} else {
let w = UnsafeMutablePointer<waiter>.allocate(capacity: 1)
let _ : Void = await withCheckedContinuation({ k in
w.initialize(to: waiter(continuation: k, next: self.waitList))
self.waitList = w
os_unfair_lock_unlock(&self.lock)
})
w.deallocate()
}
}
func signal() {
os_unfair_lock_lock(&self.lock)
if let w = self.waitList {
self.waitList = w.pointee.next
w.pointee.continuation.resume()
} else {
self.value += 1
}
os_unfair_lock_unlock(&self.lock)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment