I walked away from WWDC 2016 with the understanding that we should be wary about using C-based struct
API directly from Swift. In Concurrent Programming With GCD in Swift 3, talking about C-based locks, they were very specific:
... And in Swift, since you have the entire Darwin module at your disposition, you will actually see the
struct
based traditional C locks. However, Swift assumes that anything that isstruct
can be moved, and that doesn't work with a mutex or with a lock. So we really discourage you from using these kind of locks from 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 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. ...@implementation LockableObject { os_unfair_lock _lock; } - (void)lock { os_unfair_lock_lock(&_lock); } - (void)unlock { os_unfair_lock_unlock(&_lock); } @end
However, watching WWDC 2019 Developing a Great Profiling Experience, I notice that the author is using os_unfair_lock
directly from Swift, without this Objective-C wrapper, effectively:
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. Respecting the caveat in the 2016 WWDC video, I have refrained from using os_unfair_lock
directly from Swift.
So, the question is, are they being (ever so slightly) sloppy in the use of this API in this 2019 sample? Or was the 2016 video incorrect in its claims? Or has the handling of C-based struct
changed since Swift 3, now rendering this pattern safe?