Skip to content

Swift Atomics 1.1.0

Compare
Choose a tag to compare
@lorentey lorentey released this 03 Apr 21:50
· 58 commits to main since this release
6c89474

This minor release improves support for recent Swift releases, adds new functionality and resolves some known issues.

Changes

  • This release requires Swift 5.6 or better. (Clients on older toolchains will automatically remain on the 1.0 releases.) (#67)

  • AtomicReference is now unconditionally available on all supported platforms. (#65 by @Kelvin13)

  • ManagedAtomic now conforms to Sendable when its Value is Sendable. (#45)

  • RawRepresentable types can now opt into support for atomic operations on their optional values as long as their underlying RawValue also supports it. (#42 by @glessard)

    struct SomeValue: RawRepresentable, AtomicOptionalWrappable {
      var rawValue: UnsafeRawPointer
    
      init(rawValue: UnsafeRawPointer) {
        self.rawValue = rawValue
      }
    }
    
    let atomic: ManagedAtomic<SomeValue> // OK
    let atomic2: ManagedAtomic<SomeValue?> // Also OK!
  • The weakCompareExchange operation now comes with a variant that takes a single ordering (#75). This makes it less verbose to use it in the common case where the same ordering is needed on both the success and the failure paths.

    let atomic = ManagedAtomic<Int>(42)
    
    var original = 0
    var exchanged = false
    repeat {
      (exchanged, original) = atomic.weakCompareExchange(
        expected: original,
        desired: 23,
        ordering: .relaxed) // no need to specify a separate failureOrdering!
    } while !exchanged
  • DoubleWord.low and DoubleWord.high are now deprecated (#70). Use first and second instead.

  • This release lays the groundwork for replacing the use of C atomics with native Swift compiler intrinsics (#74). When it eventually becomes stable, this change will allow swift-atomics to support Windows (#56), and it will resolve a multitude of build problems on other platforms (e.g., #54, #55, #62, #8). Version 1.1 ships with experimental support for building the package in this mode; however, this mode is not enabled by default, and it is subject to arbitrarily change in any future release.

Fixes

  • ManagedAtomicLazyReference no longer leaks its value when it is deinitialized (#66).

  • AtomicReference conformances on non-final classes no longer emit a compiler warning in Swift 5.7 and later (#53). Atomic references now fully support class hierarchies, but only the superclass that introduced the AtomicReference conformance can be used as the type argument to ManagedAtomic or UnsafeAtomic. This turns a previously undiagnosed type safety violation into an unconditional compile-time error:

    class Base: AtomicReference {}
    // 1.0: warning: Non-final class 'Base' cannot safely conform to protocol
    //    'AtomicValue', which requires that 'Self.AtomicRepresentation.Value'
    //    is exactly equal to 'Self'; this is an error in Swift 6
    // 1.1: OK
    
    class Derived: Base {} 
    
    let ref1: ManagedAtomic<Base> = .init(Derived()) // OK
    let ref2: ManagedAtomic<Derived> = .init(Derived())
    // 1.0:
    //    no error, silent type safety violation
    // 1.1+: 
    //    error: 'ManagedAtomic' requires the types 'Derived' 
    //    and 'Base' be equivalent
  • All atomic operations are now implemented in terms of Int8, Int16, Int32, Int64, Int, or DoubleWord. The package no longer uses non-standard C to implement atomic operations on Bool (#37).

  • Building the package tests is now far less resource-intensive, considerably speeding up builds on some memory-constrained systems (#71).

Pull Requests

  • #42 Implement AtomicStorage for Optionals of RawRepresentable types (by @glessard)
  • #58 Fix support for non-final classes in AtomicReference (by @lorentey)
  • #65 enable AtomicReference everywhere (by @Kelvin13)
  • #67 Bump minimum required toolchain to Swift 5.6 (by @lorentey)
  • #68 Remove obsolete workarounds for older toolchains (by @lorentey)
  • #69 ManagedAtomicLazyReference: Properly dispose object on deinit (by @lorentey)
  • #70 Simplify shims (by @lorentey)
  • #71 Resolve some test issues (by @lorentey)
  • #72 [test] Fix basic tests to to actually cover weakCompareExchange (by @lorentey)
  • #73 Update AtomicOptionalWrappable support for RawRepresentable types (by @lorentey)
  • #74 Add support for using LLVM intrinsics instead of C atomics (by @lorentey)
  • #76 Add a weakCompareExchange variant that only takes a single ordering (by @lorentey)
  • #77 Add an Xcode project exercising native builtins in a monomodule configuration (by @lorentey)
  • #78 Fix compatibility with Swift 5.6 (by @lorentey)
  • #80 Update file headers (by @lorentey)
  • #81 Fix some edge cases under 5.6 (by @lorentey)
  • #82 1.1 release preparations (by @lorentey)
  • #83 Utilities/run-full-tests.sh: Use a different derived data path when building the Xcode project (by @lorentey)

Full diffs: 1.0.3...1.1.0

Thank you very much to everyone who contributed to this release!