# swift-atomics gives Swift explicit ordering where the standard library now has Atomic

> Apple's swift-atomics package exposes atomic operations for Swift types with explicit memory ordering and a ManagedAtomic wrapper, built for systems programmers who need to write synchronization primitives themselves. The package's own README warns that Swift 6.0's struct Atomic in the Synchronization module has largely superseded it.

**apple/swift-atomics** — Low-level atomic operations for Swift

- Repository: https://github.com/apple/swift-atomics
- Stars: 1,202 · Forks: 65
- Language: Swift
- License: Apache-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/apple-swift-atomics

## Atomic operations that ignore Swift's exclusivity rules

Swift normally enforces exclusivity, so overlapping accesses to the same variable are checked at runtime. Atomic operations sit outside that system. The documentation states that the same memory location may be safely read and updated from multiple threads of execution, as long as every access goes through an atomic operation. The counter example in the README is the shortest possible demonstration, incrementing one value ten million times across concurrent iterations:

```swift
import Atomics
import Dispatch

let counter = ManagedAtomic<Int>(0)

DispatchQueue.concurrentPerform(iterations: 10) { _ in
  for _ in 0 ..< 1_000_000 {
    counter.wrappingIncrement(ordering: .relaxed)
  }
}
counter.load(ordering: .relaxed) // ⟹ 10_000_000
```

The important detail is the shape of the API rather than the counter itself. You never read the stored value directly. Every access goes through a method that carries a memory ordering argument, so the compiler forces you to state what you mean by that access.

## No default memory ordering, on purpose

The package refuses to guess about ordering. There is no default memory ordering, and the stated reason is to avoid accidental and costly use of sequential consistency, which the README calls a surprisingly common issue in C and C++. Every operation demands an explicit ordering value, and the implementation supports a subset of the C and C++ memory orderings. The consequence for a reader is that migrating code from another language gets slower. A line that read `counter.fetch_add(1)` in C needs an explicit ordering in Swift, and a caller who picks the wrong one can reintroduce exactly the performance problem the design was meant to prevent. This is a deliberate trade of convenience for a property that only matters on hot paths, and the API design is described as prioritising clarity over superficial convenience.

## The API avoids inout parameters for compare and exchange

Compare and exchange operations in this package keep input values separate from results, and there are no `inout` parameters anywhere in the public surface. The reasoning is visible in the API itself: with an `inout` parameter, the argument you pass in and the value you get back share a slot, which makes it easy to read a result as if it were an input. Separating them means the call site always shows which value is the proposal and which is the observed value. The design also spells out every operation with a clear, unabbreviated name that says what it does, so atomic operations are never implicit. That readability has a cost in line length, and it is worth deciding early whether your team wants that verbosity in code that gets reviewed often.

## Lock-free does not mean wait-free

The README has a section separating lock-free from wait-free operations, and the distinction is the one people most often get wrong when they read about atomics. A lock-free operation guarantees that some thread makes progress, so the system as a whole keeps moving even if one thread stalls. A wait-free operation guarantees that the calling thread itself completes in a bounded number of steps. The package exposes both categories of operation across the types it supports, and the documentation treats the difference as something the caller has to reason about per operation rather than something the library decides. Swift supports only a subset of the C and C++ orderings, so a technique you read about in a C++ lock-free algorithm may not have a direct equivalent here, and you have to check what the package actually provides for the type you need.

## Memory management for atomic storage

The package covers more than integers and pointers. It provides atomic operations for a variety of Swift types, and the feature list includes memory management support, so the question of how a stored value's lifetime is handled is part of the design rather than an afterthought. For a systems programmer building a lock-free container, that is the part that decides whether the library is usable at all, since a container that cannot manage the lifetime of the values it stores is not a container. The documentation frames the whole package as existing to support the few cases where atomics are unavoidable, such as when implementing higher-level synchronization and concurrency constructs. Read that as a scoping statement: this is infrastructure for library authors, not something a typical application layer should be reaching for.

## Adding the package as a SwiftPM dependency

The package is added the usual Swift Package Manager way, by declaring the repository URL and a version requirement, then depending on the `Atomics` product by name:

```swift
// swift-tools-version:5.9
import PackageDescription

let package = Package(
  name: "MyPackage",
  dependencies: [
    .package(
      url: "https://github.com/apple/swift-atomics.git", 
      .upToNextMajor(from: "1.2.0") // or `.upToNextMinor
    )
  ],
  targets: [
    .target(
      name: "MyTarget",
      dependencies: [
        .product(name: "Atomics", package: "swift-atomics")
      ]
    )
  ]
)
```

The version requirement in the example is `1.2.0` with `.upToNextMajor`, and the comment notes `.upToNextMinor` as the alternative. The `swift-tools-version:5.9` line is what your own manifest needs to declare for that manifest to build, and it is worth matching to the toolchain you actually run.

## The compatibility table narrows as Swift moves

This package is unusually tightly coupled to the compiler, and the documentation says so plainly. Tagged versions support a narrow band of Swift releases: the 1.0.x line covers Swift 5.3 to 5.5, 1.1.x covers 5.6 to 5.8, and 1.2.x covers 5.7 to 5.9. The `main` branch tracks 5.8, 5.9 and unreleased snapshots of 5.10 and trunk, and the README states plainly that `main` is not a tagged release, that its contents are inherently unstable, and that it is not recommended for production use. That is a real operational cost: when your team moves to a new compiler, you move the package version too, and you inherit a new supported band. The project also states that new versions will periodically require clients to upgrade their Swift toolchain, so a new release is not a purely additive event.

## What is public API and what can vanish

The package is source stable and follows Semantic Versioning, so source breaking changes to the public API can only land in a new major version. Public API means non-underscored declarations marked `public` in the `Atomics` module, and the README spells out what that excludes: an underscored member such as `FooModule.Bar._someMember(value:)`, an underscored type, an underscored module, an underscored initializer. Anything with a leading underscore anywhere in its fully qualified name is fair game to change in any release, including a patch release. The `_AtomicsShims` module is explicitly not public API and may be removed outright, and the same is said of the `Utilities`, `Tests`, `Xcode` and `cmake` subdirectories. If you need an underscored API, the project asks for a feature request rather than relying on it.

## Conclusion

Adopt swift-atomics when you maintain existing code built on ManagedAtomic, or when you are on a Swift toolchain older than 6.0 and need atomic primitives with explicit ordering. Do not start new work on it, because the package itself points new code at struct Atomic in the Synchronization module. Before you migrate, check which Swift versions your tagged release supports, since the compatibility table is narrow, and check whether your code touches underscored APIs, whose contents the project reserves the right to change in any release, including patch releases.

## FAQ

### Is swift-atomics still recommended for new Swift code?

The README carries a warning that as of Swift 6.0 the package has been largely superseded by `struct Atomic` in the Synchronization module of the Swift standard library, and it asks developers to adopt the standard solution in newly written code. Existing code keeps working.

### How do I add swift-atomics to a Swift package?

Declare the repository URL as a package dependency with a version requirement, then depend on the `Atomics` product in your target. The README example uses `.upToNextMajor(from: "1.2.0")` and notes `.upToNextMinor` as the alternative.

### Which Swift versions does the latest swift-atomics release support?

The table lists a narrow band for each tag it covers: 1.0.x supports Swift 5.3 to 5.5, 1.1.x supports 5.6 to 5.8, and 1.2.x supports 5.7 to 5.9. The `main` branch tracks 5.8, 5.9 and unreleased snapshots, and it is not recommended for production use.

### Why does every atomic operation in swift-atomics take an ordering argument?

There is no default memory ordering, by design, so that sequential consistency is never used by accident. The package supports a subset of the C and C++ memory orderings and requires an explicit value on every operation.

### What is the licence of swift-atomics?

The repository is published under the Apache-2.0 licence, with the licence text held in the LICENSE.txt file at the root of the repository.

## Sources

- [apple/swift-atomics on GitHub](https://github.com/apple/swift-atomics)
- [Issues](https://github.com/apple/swift-atomics/issues)
- [License: Apache-2.0](https://github.com/apple/swift-atomics/blob/main/LICENSE)
- [README](https://github.com/apple/swift-atomics/blob/main/README.md)
- [Releases](https://github.com/apple/swift-atomics/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/apple-swift-atomics
