簡體   English   中英

我們可以直接從 Swift 使用基於 API 的 C 結構嗎?

[英]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.

然后,您將公開lockunlock方法,如果您還需要它,還有一個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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM