您的self-answer 的另一种(可能更直接)方法是直接在 Swift 中堆分配锁,而不是桥接到 Objective-C 来执行此操作。 Objective-C 方法通过从不同的语言调用具有不同语义的锁定函数来避免这个问题——C 和 Objective-C 不会 move 或墓碑值类型通过 inout 引用传递给函数;但是你也可以通过不使用 inout 引用来避免纯 Swift 中的问题:
let lock = UnsafeMutablePointer<os_unfair_lock>.allocate(capacity: 1)
lock.initialize(to: .init())
// later:
os_unfair_lock_lock(lock)
defer { os_unfair_lock_unlock(lock) }
堆分配允许您将指针直接传递到函数中,并且指针在 Swift 中是 reference 类型 — 虽然 Swift 可以移动指针值本身,但它引用的内存将保持不变(并且有效)。
如果你走这条路,当你想拆锁的时候别忘了去初始化和释放内存:
lock.deinitialize(count: 1)
lock.deallocate()
如果您愿意,您可以在 Swift 中创建类似的UnfairLock 接口,包括您自己的mutexExecute 等功能:
typealias UnfairLock = UnsafeMutablePointer<os_unfair_lock>
extension UnfairLock {
static func createLock() -> UnfairLock {
let l = UnfairLock.allocate(capacity: 1)
l.initialize(to: .init())
return l
}
static func destructLock(_ lock: UnfairLock) {
lock.deinitialize(count: 1)
lock.deallocate()
}
func whileLocked<T>(_ action: () throws -> T) rethrows -> T {
os_unfair_lock_lock(self)
defer { os_unfair_lock_unlock(self) }
return try action()
}
}
用法:
init() {
lock = UnfairLock.createLock()
}
deinit {
UnfairLock.destructLock(lock)
}
func performThing() -> Foo {
return lock.whileLocked {
// some operation that returns a Foo
}
}