Last active
April 27, 2024 13:29
-
-
Save Alexander-Ignition/8449b48e573464f23e07268e5bbcb229 to your computer and use it in GitHub Desktop.
implementation OSAllocatedUnfairLock
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import os.lock | |
public struct OSAllocatedUnfairLock<State>: @unchecked Sendable { | |
private let buffer: ManagedBuffer<State, os_unfair_lock_s> | |
public init(uncheckedState initialState: State) { | |
self.buffer = ManagedBuffer.create(minimumCapacity: 1, makingHeaderWith: { _ in | |
initialState | |
}) | |
} | |
public func withLockUnchecked<R>(_ body: (inout State) throws -> R) rethrows -> R { | |
try buffer.withUnsafeMutablePointers { state, lock in | |
os_unfair_lock_lock(lock) | |
defer { | |
os_unfair_lock_unlock(lock) | |
} | |
return try body(&state.pointee) | |
} | |
} | |
public func withLock<R>(_ body: @Sendable (inout State) throws -> R) rethrows -> R where R: Sendable { | |
try withLockUnchecked(body) | |
} | |
public func withLockIfAvailableUnchecked<R>(_ body: (inout State) throws -> R) rethrows -> R? { | |
try buffer.withUnsafeMutablePointers { state, lock in | |
guard os_unfair_lock_trylock(lock) else { | |
return nil | |
} | |
defer { | |
os_unfair_lock_unlock(lock) | |
} | |
return try body(&state.pointee) | |
} | |
} | |
public func withLockIfAvailable<R>(_ body: @Sendable (inout State) throws -> R) rethrows -> R? where R: Sendable { | |
try withLockIfAvailableUnchecked(body) | |
} | |
public enum Ownership: Hashable, Sendable { | |
case owner | |
case notOwner | |
} | |
public func precondition(_ condition: Ownership) { | |
buffer.withUnsafeMutablePointerToElements { lock in | |
switch condition { | |
case .owner: | |
os_unfair_lock_assert_owner(lock) | |
case .notOwner: | |
os_unfair_lock_assert_not_owner(lock) | |
} | |
} | |
} | |
} | |
extension OSAllocatedUnfairLock where State : Sendable { | |
public init(initialState: State) { | |
self.init(uncheckedState: initialState) | |
} | |
} | |
extension OSAllocatedUnfairLock where State == () { | |
public init() { | |
self.init(uncheckedState: ()) | |
} | |
public func withLockUnchecked<R>(_ body: () throws -> R) rethrows -> R { | |
try buffer.withUnsafeMutablePointerToElements { lock in | |
os_unfair_lock_lock(lock) | |
defer { | |
os_unfair_lock_unlock(lock) | |
} | |
return try body() | |
} | |
} | |
public func withLock<R>(_ body: @Sendable () throws -> R) rethrows -> R where R: Sendable { | |
try withLockUnchecked(body) | |
} | |
public func withLockIfAvailableUnchecked<R>(_ body: () throws -> R) rethrows -> R? { | |
try buffer.withUnsafeMutablePointerToElements { lock in | |
guard os_unfair_lock_trylock(lock) else { | |
return nil | |
} | |
defer { | |
os_unfair_lock_unlock(lock) | |
} | |
return try body() | |
} | |
} | |
public func withLockIfAvailable<R>(_ body: @Sendable () throws -> R) rethrows -> R? where R: Sendable { | |
try withLockIfAvailableUnchecked(body) | |
} | |
public func lock() { | |
buffer.withUnsafeMutablePointerToElements { lock in | |
os_unfair_lock_lock(lock) | |
} | |
} | |
public func unlock() { | |
buffer.withUnsafeMutablePointerToElements { lock in | |
os_unfair_lock_unlock(lock) | |
} | |
} | |
public func lockIfAvailable() -> Bool { | |
buffer.withUnsafeMutablePointerToElements { lock in | |
os_unfair_lock_trylock(lock) | |
} | |
} | |
} |
Author
Alexander-Ignition
commented
Apr 27, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment