Skip to content

Instantly share code, notes, and snippets.

@swhitty
Last active April 18, 2023 02:07
Show Gist options
  • Save swhitty/5c1edc9bd5dc0cd7650ccf1c14bbe32e to your computer and use it in GitHub Desktop.
Save swhitty/5c1edc9bd5dc0cd7650ccf1c14bbe32e to your computer and use it in GitHub Desktop.
@_implementationOnly import os
// Backports the Swift interface around os_unfair_lock_t available in recent Darwin platforms
// https://github.com/swhitty/AllocatedLock
//
@available(iOS, deprecated: 16.0, message: "use OSAllocatedUnfairLock directly")
@available(tvOS, deprecated: 16.0, message: "use OSAllocatedUnfairLock directly")
@available(watchOS, deprecated: 9, message: "use OSAllocatedUnfairLock directly")
@available(macOS, deprecated: 13.0, message: "use OSAllocatedUnfairLock directly")
public struct AllocatedLock<State>: @unchecked Sendable {
@usableFromInline
let storage: Storage
public init(initialState: State) {
self.storage = Storage(initialState: initialState)
}
@inlinable
public func withLock<R>(_ body: @Sendable (inout State) throws -> R) rethrows -> R where R: Sendable {
storage.lock()
defer { storage.unlock() }
return try body(&storage.state)
}
}
public extension AllocatedLock where State == Void {
init() {
self.storage = Storage(initialState: ())
}
@inlinable @available(*, noasync)
func lock() {
storage.lock()
}
@inlinable @available(*, noasync)
func unlock() {
storage.unlock()
}
@inlinable
func withLock<R>(_ body: @Sendable () throws -> R) rethrows -> R where R: Sendable {
storage.lock()
defer { storage.unlock() }
return try body()
}
}
@_implementationOnly import os
extension AllocatedLock {
@usableFromInline
final class Storage {
private let _lock: os_unfair_lock_t
@usableFromInline
var state: State
init(initialState: State) {
self._lock = .allocate(capacity: 1)
self._lock.initialize(to: os_unfair_lock())
self.state = initialState
}
@usableFromInline
func lock() {
os_unfair_lock_lock(_lock)
}
@usableFromInline
func unlock() {
os_unfair_lock_unlock(_lock)
}
deinit {
self._lock.deinitialize(count: 1)
self._lock.deallocate()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment