Some atomic functions made available to Swift 3.1 and up, including Swift 5.3
This project bridges a subset of Clang's C11 atomics support to Swift, in a manner compatible with SE-0282. This package has been the underlying guts of the long-standing (but now deprecated) SwiftAtomics package since 2017.
CAtomics
provides atomic operations to Swift using a C-style interface.
CAtomics
implements the following types:
AtomicRawPointer
,AtomicMutableRawPointer
,AtomicOpaquePointer
, and versions forOptional
pointers (AtomicOptionalRawPointer
, etc.);AtomicInt
andAtomicUInt
, as well as signed and unsigned versions of the 8-bit, 16-bit, 32-bit and 64-bit integer types;AtomicBool
Functions defined in CAtomics
are prefixed with CAtomics
. All types define CAtomicsLoad
, CAtomicsStore
, CAtomicsExchange
, CAtomicsCompareAndExchangeWeak
and CAtomicsCompareAndExchangeStrong
. Additionally, the integer types define CAtomicsAdd
, CAtomicsSubtract
, CAtomicsBitwiseAnd
, CAtomicsBitwiseOr
and CAtomicsBitwiseXor
. Finally, AtomicBool
defines CAtomicsAnd
, CAtomicsOr
, and CAtomicsXor
.
The memory ordering (from <stdatomic.h>
) can be set by using the order: MemoryOrder
parameter on each method.
public enum MemoryOrder : UInt32 {
case relaxed, acquire, release, acqrel, sequential
}
Note that memory_order_consume
has no equivalent in this module, as (as far as I can tell) clang silently upgrades that ordering to memory_order_acquire
, making it impossible (at the moment) to test whether an algorithm can properly use memory_order_consume
. This also means nothing is lost by its absence.
Atomic types are useful as synchronization points between threads, and therefore have an interesting relationship with Swift's exclusivity checking. They should be initialized at fixed memory locations, such as members of reference types, captured by closures, or in heap allocations. This being said, although the first two work as expected with current Swift, only the latter (heap allocations) is compatible with the thread sanitizer.
In order to use atomics in a way that is acceptable to the thread sanitizer, one must allocate memory for atomic variables using UnsafeMutablePointer
. Then, pass that pointer to the functions defined in the CAtomics
module, as needed.
import CAtomics
class Example {
private var counter = UnsafeMutablePointer<AtomicInt>.allocate(capacity: 1)
init() {
CAtomicsInitialize(counter, 0)
}
deinit {
counter.deallocate()
}
func increment(by value: Int = 1) {
CAtomicsAdd(counter, value, .relaxed)
}
}
This library requires Swift 3.1 or later. On Linux, it also requires Clang 3.6 or later.