Skip to content

Commit cd142fd

Browse files
authored
Merge pull request #106 from lorentey/release-cleanup
Not so minor prerelease fixups/changes
2 parents d8a5239 + 3431b85 commit cd142fd

File tree

53 files changed

+8753
-6426
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+8753
-6426
lines changed

CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ endif()
2525
include(CTest)
2626
include(SwiftSupport)
2727

28+
set(ATOMICS_SWIFT_FLAGS)
29+
set(ATOMICS_C_FLAGS)
30+
31+
if(CMAKE_Swift_COMPILER_VERSION VERSION_GREATER_EQUAL 5.9)
32+
list(APPEND ATOMICS_SWIFT_FLAGS
33+
"-enable-experimental-feature BuiltinModule"
34+
"-DATOMICS_NATIVE_BUILTINS"
35+
"-Xcc" "-DATOMICS_NATIVE_BUILTINS=1")
36+
list(APPEND ATOMICS_C_FLAGS
37+
"-DATOMICS_NATIVE_BUILTINS=1")
38+
endif()
39+
2840
add_subdirectory(Sources)
2941
if(BUILD_TESTING)
3042
add_subdirectory(Tests)

README.md

Lines changed: 69 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ The primary focus is to provide systems programmers access to atomic operations
4747

4848
- Each atomic operation is invoked in client code using a clear, unabbreviated name that directly specifies what that operation does. Atomic operations are never implicit -- they are always clearly spelled out.
4949

50-
- There is no default memory ordering, to avoid accidental (and costly) use of sequential consistency. (This is surprisingly common issue in C/C++.)
50+
- There is no default memory ordering, to avoid accidental (and costly) use of sequential consistency. (This is a surprisingly common issue in C/C++.)
5151

5252
- Operations such as compare/exchange prefer to keep input values cleanly separated from results. There are no `inout` parameters.
5353

@@ -56,15 +56,15 @@ The primary focus is to provide systems programmers access to atomic operations
5656
To use `Atomics` in your own project, you need to set it up as a package dependency:
5757

5858
```swift
59-
// swift-tools-version:5.6
59+
// swift-tools-version:5.9
6060
import PackageDescription
6161

6262
let package = Package(
6363
name: "MyPackage",
6464
dependencies: [
6565
.package(
6666
url: "https://github.com/apple/swift-atomics.git",
67-
.upToNextMajor(from: "1.1.0") // or `.upToNextMinor
67+
.upToNextMajor(from: "1.2.0") // or `.upToNextMinor
6868
)
6969
],
7070
targets: [
@@ -78,20 +78,76 @@ let package = Package(
7878
)
7979
```
8080

81+
## Compatibility
82+
83+
### Swift Releases
84+
85+
The atomics implementation is inherently far more tightly coupled to the compiler than usual, so tagged versions of this package typically only support a narrow range of Swift releases:
86+
87+
swift-atomics | Supported Swift Versions
88+
--------------------|-------------------------
89+
`1.0.x` | 5.3, 5.4, 5.5
90+
`1.1.x` | 5.6, 5.7, 5.8
91+
`1.2.x` | 5.7, 5.8, 5.9
92+
`main` | 5.8, 5.9, unreleased snapshots of 5.10 and trunk
93+
94+
Note that the `main` branch is not a tagged release, so its contents are inherently unstable. Because of this, we do not recommended using it in production. (For example, its set of supported Swift releases is subject to change without notice.)
95+
96+
### Source Stability
97+
98+
The Swift Atomics package is source stable. The version numbers follow [Semantic Versioning][semver] -- source breaking changes to public API can only land in a new major version.
99+
100+
[semver]: https://semver.org
101+
102+
The public API of current versions of the `swift-atomics` package consists of non-underscored declarations that are marked `public` in the `Atomics` module.
103+
104+
By "underscored declarations" we mean declarations that have a leading underscore anywhere in their fully qualified name. For instance, here are some names that wouldn't be considered part of the public API, even if they were technically marked public:
105+
106+
- `FooModule.Bar._someMember(value:)` (underscored member)
107+
- `FooModule._Bar.someMember` (underscored type)
108+
- `_FooModule.Bar` (underscored module)
109+
- `FooModule.Bar.init(_value:)` (underscored initializer)
110+
111+
Interfaces that aren't part of the public API may continue to change in any release, including patch releases.
112+
113+
Note that contents of the `_AtomicsShims` module explicitly aren't public API. (As implied by its underscored module name.) The definitions therein may therefore change at whim, and the entire module may be removed in any new release -- do not import this module directly. We also don't make any source compatibility promises about the contents of the `Utilities`, `Tests`, `Xcode` and `cmake` subdirectories.
114+
115+
If you have a use case that requires using underscored APIs, please [submit a Feature Request][enhancement] describing it! We'd like the public interface to be as useful as possible -- although preferably without compromising safety or limiting future evolution.
116+
117+
Future minor versions of the package may introduce changes to these rules as needed.
118+
119+
We'd like this package to quickly embrace Swift language and toolchain improvements that are relevant to its mandate. Accordingly, from time to time, new versions of this package will require clients to upgrade to a more recent Swift toolchain release. (This allows the package to make use of new language/stdlib features, build on compiler bug fixes, and adopt new package manager functionality as soon as they are available.)
120+
121+
Requiring a new Swift release will only require a minor version bump.
122+
123+
81124
## Features
82125

83-
The package implements atomic operations for the following Swift constructs, all of which conform to the public `AtomicValue` protocol:
126+
For a detailed overview of the interfaces offered by this package, please see [our API documentation][APIDocs].
127+
128+
[APIDocs]: https://swiftpackageindex.com/apple/swift-atomics/1.2.0/documentation/atomics
129+
[AtomicValue]: https://swiftpackageindex.com/apple/swift-atomics/1.2.0/documentation/atomics/atomicvalue
130+
[DoubleWord]: https://swiftpackageindex.com/apple/swift-atomics/1.2.0/documentation/atomics/doubleword
131+
[AtomicReference]: https://swiftpackageindex.com/apple/swift-atomics/1.2.0/documentation/atomics/atomicreference
132+
[UnsafeAtomic]: https://swiftpackageindex.com/apple/swift-atomics/1.2.0/documentation/atomics/unsafeatomic
133+
[ManagedAtomic]: https://swiftpackageindex.com/apple/swift-atomics/1.2.0/documentation/atomics/managedatomic
134+
[ManagedAtomicLazyReference]: https://swiftpackageindex.com/apple/swift-atomics/1.2.0/documentation/atomics/managedatomiclazyreference
135+
[UnsafeAtomicLazyReference]: https://swiftpackageindex.com/apple/swift-atomics/1.2.0/documentation/atomics/unsafeatomiclazyreference
136+
[AtomicStorage]: https://swiftpackageindex.com/apple/swift-atomics/1.2.0/documentation/atomics/atomicstorage
137+
[AtomicInteger]: https://swiftpackageindex.com/apple/swift-atomics/1.2.0/documentation/atomics/atomicinteger
138+
139+
The package implements atomic operations for the following Swift constructs, all of which conform to the public [`AtomicValue` protocol][AtomicValue]:
84140

85141
- Standard signed integer types (`Int`, `Int64`, `Int32`, `Int16`, `Int8`)
86142
- Standard unsigned integer types (`UInt`, `UInt64`, `UInt32`, `UInt16`, `UInt8`)
87143
- Booleans (`Bool`)
88144
- Standard pointer types (`UnsafeRawPointer`, `UnsafeMutableRawPointer`, `UnsafePointer<T>`, `UnsafeMutablePointer<T>`), along with their optional-wrapped forms (such as `Optional<UnsafePointer<T>>`)
89145
- Unmanaged references (`Unmanaged<T>`, `Optional<Unmanaged<T>>`)
90-
- A special `DoubleWord` type that consists of two `UInt` values, `first` and `second`, providing double-wide atomic primitives
146+
- A special [`DoubleWord` type][DoubleWord] that consists of two `UInt` values, `first` and `second`, providing double-wide atomic primitives
91147
- Any `RawRepresentable` type whose `RawValue` is in turn an atomic type (such as simple custom enum types)
92-
- Strong references to class instances that opted into atomic use (by conforming to the `AtomicReference` protocol)
148+
- Strong references to class instances that opted into atomic use (by conforming to the [`AtomicReference` protocol][AtomicReference])
93149

94-
Of particular note is full support for atomic strong references. This provides a convenient memory reclamation solution for concurrent data structures that fits perfectly with Swift's reference counting memory management model. (Atomic strong references are implemented in terms of `DoubleWord` operations.) However, accessing an atomic strong reference is (relatively) expensive, so we also provide a separate set of efficient constructs (`ManagedAtomicLazyReference` and `UnsafeAtomicLazyReference`) for the common case of a lazily initialized (but otherwise constant) atomic strong reference.
150+
Of particular note is full support for atomic strong references. This provides a convenient memory reclamation solution for concurrent data structures that fits perfectly with Swift's reference counting memory management model. (Atomic strong references are implemented in terms of `DoubleWord` operations.) However, accessing an atomic strong reference is (relatively) expensive, so we also provide a separate set of efficient constructs ([`ManagedAtomicLazyReference`][ManagedAtomicLazyReference] and [`UnsafeAtomicLazyReference`][UnsafeAtomicLazyReference]) for the common case of a lazily initialized (but otherwise constant) atomic strong reference.
95151

96152
### Lock-Free vs Wait-Free Operations
97153

@@ -107,12 +163,12 @@ Atomic access is implemented in terms of dedicated atomic storage representation
107163

108164
[SE-0282]: https://github.com/apple/swift-evolution/blob/master/proposals/0282-atomics.md
109165

110-
While the underlying pointer-based atomic operations are exposed as static methods on the corresponding `AtomicStorage` types, we strongly recommend the use of higher-level atomic wrappers to manage the details of preparing/disposing atomic storage. This version of the library provides two wrapper types:
166+
While the underlying pointer-based atomic operations are exposed as static methods on the corresponding [`AtomicStorage`][AtomicStorage] types, we strongly recommend the use of higher-level atomic wrappers to manage the details of preparing/disposing atomic storage. This version of the library provides two wrapper types:
111167

112-
- an easy to use, memory-safe `ManagedAtomic<T>` generic class and
113-
- a less convenient, but more flexible `UnsafeAtomic<T>` generic struct.
168+
- an easy to use, memory-safe [`ManagedAtomic<T>`][ManagedAtomic] generic class and
169+
- a less convenient, but more flexible [`UnsafeAtomic<T>`][UnsafeAtomic] generic struct.
114170

115-
Both constructs provide the following operations on all `AtomicValue` types:
171+
Both constructs provide the following operations on all [`AtomicValue`][AtomicValue] types:
116172

117173
```swift
118174
func load(ordering: AtomicLoadOrdering) -> Value
@@ -146,7 +202,7 @@ func weakCompareExchange(
146202
) -> (exchanged: Bool, original: Value)
147203
```
148204

149-
Integer types come with additional atomic operations for incrementing or decrementing values and bitwise logical operations.
205+
[Integer types][AtomicInteger] come with additional atomic operations for incrementing or decrementing values and bitwise logical operations.
150206

151207
```swift
152208
func loadThenWrappingIncrement(
@@ -247,34 +303,7 @@ func logicalXorThenLoad(
247303

248304
For an introduction to the APIs provided by this package, for now please see the [first version of SE-0282][SE-0282r0].
249305

250-
The current version of the `Atomics` module does not implement APIs for tagged atomics (see [issue #1](https://github.com/apple/swift-atomics/issues/1)), although it does expose a `DoubleWord` type that can be used to implement them. (Atomic strong references are already implemented in terms of `DoubleWord`, although in their current form they do not expose any user-customizable bits.)
251-
252-
## Source Stability
253-
254-
The Swift Atomics package is source stable. The version numbers follow [Semantic Versioning][semver] -- source breaking changes to public API can only land in a new major version.
255-
256-
[semver]: https://semver.org
257-
258-
The public API of version 1.1 of the `swift-atomics` package consists of non-underscored declarations that are marked `public` in the `Atomics` module.
259-
260-
By "underscored declarations" we mean declarations that have a leading underscore anywhere in their fully qualified name. For instance, here are some names that wouldn't be considered part of the public API, even if they were technically marked public:
261-
262-
- `FooModule.Bar._someMember(value:)` (underscored member)
263-
- `FooModule._Bar.someMember` (underscored type)
264-
- `_FooModule.Bar` (underscored module)
265-
- `FooModule.Bar.init(_value:)` (underscored initializer)
266-
267-
Interfaces that aren't part of the public API may continue to change in any release, including patch releases.
268-
269-
Note that contents of the `_AtomicsShims` module explicitly aren't public API. (As implied by its underscored module name.) The definitions therein may therefore change at whim, and the entire module may be removed in any new release -- do not import this module directly. We also don't make any source compatibility promises about the contents of the `Utilities`, `Tests`, `Xcode` and `cmake` subdirectories.
270-
271-
If you have a use case that requires using underscored APIs, please [submit a Feature Request][enhancement] describing it! We'd like the public interface to be as useful as possible -- although preferably without compromising safety or limiting future evolution.
272-
273-
Future minor versions of the package may introduce changes to these rules as needed.
274-
275-
We'd like this package to quickly embrace Swift language and toolchain improvements that are relevant to its mandate. Accordingly, from time to time, new versions of this package will require clients to upgrade to a more recent Swift toolchain release. (This allows the package to make use of new language/stdlib features, build on compiler bug fixes, and adopt new package manager functionality as soon as they are available.)
276-
277-
Requiring a new Swift release will only require a minor version bump.
306+
The current version of the `Atomics` module does not implement APIs for tagged atomics (see [issue #1](https://github.com/apple/swift-atomics/issues/1)), although it does expose a [`DoubleWord`][DoubleWord] type that can be used to implement them. (Atomic strong references are already implemented in terms of [`DoubleWord`][DoubleWord], although in their current form they do not expose any user-customizable bits.)
278307

279308
## Contributing to Swift Atomics
280309

Sources/Atomics/Atomics.docc/Extensions/AtomicRawRepresentableStorage.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
- ``atomicLoad(at:ordering:)``
1313
- ``atomicStore(_:at:ordering:)``
1414
- ``atomicExchange(_:at:ordering:)``
15-
- ``atomicCompareExchange(expected:desired:at:ordering:)``
15+
- ``atomicCompareExchange(expected:desired:at:ordering:)-1teq9``
1616
- ``atomicCompareExchange(expected:desired:at:successOrdering:failureOrdering:)``
1717
- ``atomicWeakCompareExchange(expected:desired:at:successOrdering:failureOrdering:)``

Sources/Atomics/Atomics.docc/Extensions/AtomicStorage.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@
1717
- ``atomicStore(_:at:ordering:)``
1818
- ``atomicExchange(_:at:ordering:)``
1919
- ``atomicCompareExchange(expected:desired:at:ordering:)``
20-
- ``atomicCompareExchange(expected:desired:at:successOrdering:failureOrdering:)``
20+
- ``atomicCompareExchange(expected:desired:at:successOrdering:failureOrdering:)-9t4wj``
21+
- ``atomicWeakCompareExchange(expected:desired:at:ordering:)-55229``
2122
- ``atomicWeakCompareExchange(expected:desired:at:successOrdering:failureOrdering:)``

Sources/Atomics/Atomics.docc/Extensions/ManagedAtomic.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- ``exchange(_:ordering:)``
1414
- ``compareExchange(expected:desired:ordering:)``
1515
- ``compareExchange(expected:desired:successOrdering:failureOrdering:)``
16+
- ``weakCompareExchange(expected:desired:ordering:)``
1617
- ``weakCompareExchange(expected:desired:successOrdering:failureOrdering:)``
1718

1819
### Atomic Integer Operations

Sources/Atomics/Atomics.docc/Extensions/UnsafeAtomic.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
- ``exchange(_:ordering:)``
2323
- ``compareExchange(expected:desired:ordering:)``
2424
- ``compareExchange(expected:desired:successOrdering:failureOrdering:)``
25+
- ``weakCompareExchange(expected:desired:ordering:)``
2526
- ``weakCompareExchange(expected:desired:successOrdering:failureOrdering:)``
2627

2728
### Atomic Integer Operations

Sources/Atomics/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ add_library(Atomics
3131

3232
set_target_properties(Atomics PROPERTIES
3333
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
34+
target_compile_options(Atomics PUBLIC
35+
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:${ATOMICS_SWIFT_FLAGS}>"
36+
"$<$<COMPILE_LANGUAGE:C,CXX>:SHELL:${ATOMICS_C_FLAGS}>")
3437
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
3538
target_compile_options(Atomics PUBLIC
3639
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-Xcc -mcx16>")

Sources/Atomics/Conformances/AtomicBool.swift.gyb

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,37 +43,55 @@ extension Bool: AtomicValue {
4343

4444
@_transparent @_alwaysEmitIntoClient
4545
public init(_ value: Bool) {
46+
#if ATOMICS_NATIVE_BUILTINS
4647
_storage = value._atomicRepresentation
48+
#else
49+
_storage = _sa_prepare_Int8(value._atomicRepresentation)
50+
#endif
4751
}
4852

4953
@_transparent @_alwaysEmitIntoClient
5054
public func dispose() -> Value {
55+
#if ATOMICS_NATIVE_BUILTINS
5156
return _storage._decodeBool
57+
#else
58+
return _sa_dispose_Int8(_storage)._decodeBool
59+
#endif
5260
}
5361
}
62+
}
5463

64+
#if ATOMICS_NATIVE_BUILTINS
65+
extension Bool {
5566
@_transparent @_alwaysEmitIntoClient
5667
internal var _atomicRepresentation: _AtomicInt8Storage {
5768
let v: Int8 = (self ? 1 : 0)
58-
#if ATOMICS_NATIVE_BUILTINS
5969
return .init(v._value)
60-
#else
61-
return _sa_prepare_Int8(v)
62-
#endif
6370
}
6471
}
6572

6673
extension _AtomicInt8Storage {
6774
@_transparent @_alwaysEmitIntoClient
6875
internal var _decodeBool: Bool {
69-
#if ATOMICS_NATIVE_BUILTINS
70-
return (Int8(self._value) & 1) != 0
76+
(Int8(self._value) & 1) != 0
77+
}
78+
}
7179
#else
72-
return (_sa_dispose_Int8(self) & 1) != 0
73-
#endif
80+
extension Bool {
81+
@_transparent @_alwaysEmitIntoClient
82+
internal var _atomicRepresentation: Int8 {
83+
self ? 1 : 0
7484
}
7585
}
7686

87+
extension Int8 {
88+
@_transparent @_alwaysEmitIntoClient
89+
internal var _decodeBool: Bool {
90+
(self & 1) != 0
91+
}
92+
}
93+
#endif
94+
7795
extension UnsafeMutablePointer
7896
where Pointee == Bool.AtomicRepresentation {
7997
@_transparent @_alwaysEmitIntoClient

Sources/Atomics/Conformances/IntegerConformances.swift.gyb

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,20 @@ extension ${swiftType}: AtomicValue {
4848

4949
@_transparent @_alwaysEmitIntoClient
5050
public init(_ value: Value) {
51+
#if ATOMICS_NATIVE_BUILTINS
5152
_storage = Self._encode(value)
53+
#else
54+
_storage = _sa_prepare_${shimType}(Self._encode(value))
55+
#endif
5256
}
5357

5458
@_transparent @_alwaysEmitIntoClient
5559
public func dispose() -> Value {
56-
Self._decode(_storage)
60+
#if ATOMICS_NATIVE_BUILTINS
61+
return Self._decode(_storage)
62+
#else
63+
return Self._decode(_sa_dispose_${shimType}(_storage))
64+
#endif
5765
}
5866
}
5967
}
@@ -68,33 +76,39 @@ where Pointee == ${swiftType}.AtomicRepresentation {
6876
}
6977
}
7078

79+
#if ATOMICS_NATIVE_BUILTINS
7180
extension ${swiftType}.AtomicRepresentation {
7281
@_transparent @_alwaysEmitIntoClient
7382
static func _decode(_ storage: _Storage) -> Value {
74-
#if ATOMICS_NATIVE_BUILTINS
7583
return Value(storage._value)
84+
}
85+
86+
@_transparent @_alwaysEmitIntoClient
87+
static func _encode(_ value: Value) -> _Storage {
88+
return _Storage(value._value)
89+
}
90+
}
7691
#else
92+
extension ${swiftType}.AtomicRepresentation {
93+
@_transparent @_alwaysEmitIntoClient
94+
static func _decode(_ v: ${shimType}) -> Value {
7795
% if swiftType == shimType:
78-
return _sa_dispose_${shimType}(storage)
96+
return v
7997
% else:
80-
return Value(_sa_dispose_${shimType}(storage)._value)
98+
return Value(v._value)
8199
% end
82-
#endif
83100
}
84101

85102
@_transparent @_alwaysEmitIntoClient
86-
static func _encode(_ value: Value) -> _Storage {
87-
#if ATOMICS_NATIVE_BUILTINS
88-
return _Storage(value._value)
89-
#else
103+
static func _encode(_ value: Value) -> ${shimType} {
90104
% if swiftType == shimType:
91-
return _sa_prepare_${shimType}(value)
105+
return value
92106
% else:
93-
return _sa_prepare_${shimType}(${shimType}(value._value))
107+
return ${shimType}(value._value)
94108
% end
95-
#endif
96109
}
97110
}
111+
#endif
98112

99113
extension ${swiftType}.AtomicRepresentation: AtomicStorage {
100114
@_semantics("atomics.requires_constant_orderings")

0 commit comments

Comments
 (0)