[英]Can we use C struct based API directly from Swift?
I walked away from WWDC 2016 with the understanding that we should be wary about using C-based struct
API directly from Swift.我离开了 WWDC 2016,了解到我们应该警惕直接从 Swift 使用基于 C 的
struct
API。 InConcurrent Programming With GCD in Swift 3 , talking about C-based locks, they were very specific:在Swift 3 中使用 GCD 进行并发编程中,谈到基于 C 的锁,它们非常具体:
... And in Swift, since you have the entire Darwin module at your disposition, you will actually see the
struct
based traditional C locks....在 Swift 中,由于您拥有整个 Darwin 模块,您实际上会看到基于
struct
的传统 C 锁。 However, Swift assumes that anything that isstruct
can be moved, and that doesn't work with a mutex or with a lock.但是,Swift 假设任何
struct
都可以移动,并且这不适用于互斥体或锁。 So we really discourage you from using these kind of locks from Swift.因此,我们真的不鼓励您使用 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.
... 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.
And then you will expose
lock
andunlock
methods, and atryLock
if you need it as well, that you will be able to call from Swift when you will subclass this class.然后,您将公开
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
However, watching WWDC 2019Developing a Great Profiling Experience , I notice that the author is using os_unfair_lock
directly from Swift, without this Objective-C wrapper, effectively:但是,在观看 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)
...
}
Empirically, this sort of direct use of os_unfair_lock
appears to work, but that doesn't mean anything.根据经验,这种直接使用
os_unfair_lock
似乎可行,但这并不意味着什么。 Respecting the caveat in the 2016 WWDC video, I have refrained from using os_unfair_lock
directly from Swift.尊重 2016 年 WWDC 视频中的警告,我避免直接从 Swift 使用
os_unfair_lock
。
So, the question is, are they being (ever so slightly) sloppy in the use of this API in this 2019 sample?所以,问题是,他们在 2019 年的样本中使用这个 API 是否(稍微)草率? Or was the 2016 video incorrect in its claims?
还是 2016 年的视频在其声明中不正确? Or has the handling of C-based
struct
changed since Swift 3, now rendering this pattern safe?还是自 Swift 3 以来基于 C 的
struct
的处理发生了变化,现在使这种模式安全?
The API example of using private var workItemsLock = os_unfair_lock()
can fail at runtime.使用
private var workItemsLock = os_unfair_lock()
的 API 示例在运行时可能会失败。
The threading primitives from C need a stable memory location so to use them or another struct that has one of these primitives directly as a member of it you have to use UnsafePointer
.来自 C 的线程原语需要一个稳定的 memory 位置,因此要使用它们或另一个直接将这些原语之一作为其成员的结构,您必须使用
UnsafePointer
。 The reason for this is that UnsafePointer
APIs once they have allocated a chunk of memory that memory is stable and cannot be moved or trivially be copied by the compiler.原因是
UnsafePointer
API 在分配了一块 memory 后,memory 是稳定的,不能被编译器移动或轻易复制。
If you change the example like this it is now valid如果您像这样更改示例,它现在是有效的
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.