[英]Can we use C struct based API directly from Swift?
我離開了 WWDC 2016,了解到我們應該警惕直接從 Swift 使用基於 C 的struct
API。 在Swift 3 中使用 GCD 進行並發編程中,談到基於 C 的鎖,它們非常具體:
...在 Swift 中,由於您擁有整個 Darwin 模塊,您實際上會看到基於
struct
的傳統 C 鎖。 但是,Swift 假設任何struct
都可以移動,並且這不適用於互斥體或鎖。 因此,我們真的不鼓勵您使用 Swift 中的此類鎖。 ...... And if you want something... that looks like the locks that you have in C, then you have to call into Objective-C and introduce a base class in Objective-C that has your lock as an ivar.
然后,您將公開
lock
和unlock
方法,如果您還需要它,還有一個tryLock
,當您將這個 class 子類化時,您將能夠從 Swift 調用它。 ...@implementation LockableObject { os_unfair_lock _lock; } - (void)lock { os_unfair_lock_lock(&_lock); } - (void)unlock { os_unfair_lock_unlock(&_lock); } @end
但是,在觀看 WWDC 2019Developing a Great Profiling Experience時,我注意到作者是直接從 Swift 使用os_unfair_lock
,沒有這個 Objective-C 包裝器,有效:
private var workItemsLock = os_unfair_lock()
func subWorkItem(...) {
...
os_unfair_lock_lock(&self.workItemsLock)
...
os_unfair_lock_unlock(&self.workItemsLock)
...
}
根據經驗,這種直接使用os_unfair_lock
似乎可行,但這並不意味着什么。 尊重 2016 年 WWDC 視頻中的警告,我避免直接從 Swift 使用os_unfair_lock
。
所以,問題是,他們在 2019 年的樣本中使用這個 API 是否(稍微)草率? 還是 2016 年的視頻在其聲明中不正確? 還是自 Swift 3 以來基於 C 的struct
的處理發生了變化,現在使這種模式安全?
使用private var workItemsLock = os_unfair_lock()
的 API 示例在運行時可能會失敗。
來自 C 的線程原語需要一個穩定的 memory 位置,因此要使用它們或另一個直接將這些原語之一作為其成員的結構,您必須使用UnsafePointer
。 原因是UnsafePointer
API 在分配了一塊 memory 后,memory 是穩定的,不能被編譯器移動或輕易復制。
如果您像這樣更改示例,它現在是有效的
private var workItemsLock: UnsafeMutablePointer<os_unfair_lock> = {
// Note, somewhere else this will need to be deallocated
var pointer = UnsafeMutablePointer<os_unfair_lock>.allocate(capacity: 1)
pointer.initialize(to: os_unfair_lock())
return pointer
}()
func subWorkItem(...) {
...
os_unfair_lock_lock(self.workItemsLock)
...
os_unfair_lock_unlock(self.workItemsLock)
...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.