【问题标题】:Can we use C struct based API directly from Swift?我们可以直接从 Swift 使用基于 C 结构的 API 吗?
【发布时间】:2020-04-26 22:46:46
【问题描述】:

我从 WWDC 2016 离开时了解到,我们应该警惕直接从 Swift 使用基于 C 的 struct API。在Concurrent Programming With GCD in Swift 3 中,谈到基于 C 的锁,它们非常具体:

...在 Swift 中,由于您拥有整个 Darwin 模块,您实际上会看到基于 struct 的传统 C 锁。但是,Swift 假设任何 struct 都可以移动,而这不适用于互斥体或锁。所以我们真的不鼓励你从 Swift 中使用这些类型的锁。 ...

...如果您想要一些...看起来像您在 C 中拥有的锁,那么您必须调用 Objective-C 并在 Objective-C 中引入一个基类,该基类将您的锁作为 ivar .

然后您将公开lock 和unlock 方法,如果您还需要它,还可以公开tryLock,当您将此类子类化时,您将能够从Swift 调用。 ...

@implementation LockableObject {
    os_unfair_lock _lock;
}

- (void)lock   { os_unfair_lock_lock(&_lock); }
- (void)unlock { os_unfair_lock_unlock(&_lock); }
@end

但是,观看 WWDC 2019 Developing 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 的处理方式发生了变化,现在使这种模式变得安全了吗?

【问题讨论】:

    标签: c swift struct


    【解决方案1】:

    使用private var workItemsLock = os_unfair_lock() 的API 示例在运行时可能会失败。

    来自 C 语言的线程原语需要一个稳定的内存位置,因此要使用它们或其他将这些原语之一直接作为其成员的结构,您必须使用 UnsafePointer。这样做的原因是UnsafePointer API 一旦分配了一块内存,该内存是稳定的,不能被编译器移动或轻易复制。

    如果您像这样更改示例,它现在是有效的

    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)
        ...
    }
    

    【讨论】:

    • 这种allocate 模式正是Apple 拥有的done within stdlib。我的结论是 WWDC 2019 #414 代码 sn-p 有点草率,并且 WWDC 2016 演示文稿中概述的潜在问题仍然适用。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    • 1970-01-01
    • 1970-01-01
    • 2018-01-17
    相关资源
    最近更新 更多