Swift Atomics, "a new open source package that enables direct use of low-level atomic operations in Swift code", is now available:
Please feel free to ask questions about the post here!
Swift Atomics, "a new open source package that enables direct use of low-level atomic operations in Swift code", is now available:
Please feel free to ask questions about the post here!
Might it be valuable to discuss when using atomics instead of explicit locks might be appropriate? Given that ManagedAtomic
is far more approachable than the C-based atomics we had access to before, it might be to explain when Swift developers would use one or the other.
While Swift doesn't have a native lock API, you aren't limited to importing locks from C: the Dispatch and Foundation libraries already provide excellent synchronization tools! These are essentially the best we could reasonably provide in Swift today.*
* UnsafeAtomic
/ManagedAtomic
-style convenience wrappers for additional, platform-specific, synchronization constructs could perhaps find a home in the recently announced Swift System project. But I find Dispatch already provides great solutions for most use cases.
I'd never use atomics unless the situation positively forced my hand to do it. In almost all cases, straightforward synchronization using serial dispatch queues or locks is far, far easier to get right than trying to deal with atomics. And in almost all cases, the resulting code performs great.
If you have a problem that is solvable with higher-level synchronization, then going with that is invariably the right approach: it saves immense amounts of effort that would be spent on debugging subtle concurrency issues. (And all that effort would be inevitably repeated whenever the code is modified in any way.)
Of course, locking isn't always appropriate. It is incomparably more difficult to write even the most rudimentary lock-free queue data structure than a locking one, but if you're trying to implement something like the Dispatch
framework in pure Swift, then you don't really have a choice -- you must embrace atomics. Thankfully, these situations are few and far between; but Swift cannot truly be a systems programming language unless you can use it to solve these sorts of problems, too!
Congrats! Great job!
Suggestions of improvement to the Announcement page on Swift.org:
It is an LLVM tool. You can learn more about the available sanitizers, as well as how to enable them in Xcode and the command-line, here: Diagnosing memory, thread, and crash issues early | Apple Developer Documentation
What Karl said.
For a nice intro to TSan, I would also watch Anna's WWDC talk from 2016: WWDC16 - Videos - Apple Developer
When someone complains about a bug that occurs infrequently and they can't reproduce it, more often than not simply clicking the "Thread Sanitizer" box immediately reveals the problem.
Been an iOS dev for 7 years and Swift dev for 6 years - and I’ve completely missed this wow, will definitely check it out, thanks!
Congrats for the achievement.
This will be very handy in my case, given i have a thread scheduler/pool implementation that defaults to pthread, and was using the rather nice atomic interfaces from the borrowed "Atomics.swift" from the Swift NIO project.
Time to update that..
PS: The only thing missing in Swift now, to become a heavy-weight champion, is to make that sweet ownership manifesto come true.
Yupp Variadic Generics and Ownership - then my life is complete.
Simple rule of thumb: Never use "low-level" atomic and always use explicit locks.
As ManagedAtomic
is considered a low-level API, avoid it as much as possible. This is not a locking primitive, and should not be use as one. It may be useful for an atomic counter though.
C based API like pthread_mutex_t
are extremely fast when there is no contention as they are using a simple atomic CAS as fast path. If you think this is still too heavy for your need, consider something like unfair lock
API. But never try to rewrite synchronisation primitive unless you really know what you're doing.
Congrats