Skip to content

Commit 2e9df4f

Browse files
authored
Don't use Synchronization.Atomic for deliverExpectationCheckedEvents. (swiftlang#666)
This PR replaces the new use of `Atomic<Int>` with a `Locked<Int>` in the implementation of `deliverExpectationCheckedEvents`. Why? Because we're running into some environments where the Synchronization module isn't available (e.g. older host macOSes) and this is simpler. The performance profile is comparable: on my system, running the `repeatedlyExpect()` test takes 0.55s instead of 0.49s to call `#expect()` 1,000,000 times, so it's still a significant win over the implementation we had earlier. ### Checklist: - [x] Code and documentation should follow the style of the [Style Guide](https://github.com/apple/swift-testing/blob/main/Documentation/StyleGuide.md). - [x] If public symbols are renamed or modified, DocC references should be updated.
1 parent ca51589 commit 2e9df4f

File tree

4 files changed

+15
-15
lines changed

4 files changed

+15
-15
lines changed

Package.swift

-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ extension Array where Element == PackageDescription.SwiftSetting {
148148
.enableExperimentalFeature("AvailabilityMacro=_clockAPI:macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0"),
149149
.enableExperimentalFeature("AvailabilityMacro=_regexAPI:macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0"),
150150
.enableExperimentalFeature("AvailabilityMacro=_swiftVersionAPI:macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0"),
151-
.enableExperimentalFeature("AvailabilityMacro=_synchronizationAPI:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0"),
152151
.enableExperimentalFeature("AvailabilityMacro=_typedThrowsAPI:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0"),
153152

154153
.enableExperimentalFeature("AvailabilityMacro=_distantFuture:macOS 99.0, iOS 99.0, watchOS 99.0, tvOS 99.0, visionOS 99.0"),

Sources/Testing/Running/Runner.RuntimeState.swift

+6-13
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
99
//
1010

11-
private import Synchronization
12-
1311
extension Runner {
1412
/// A type which collects the task-scoped runtime state for a running
1513
/// ``Runner`` instance, the tests it runs, and other objects it interacts
@@ -113,8 +111,8 @@ extension Configuration {
113111
/// - Returns: A unique number identifying `self` that can be
114112
/// passed to `_removeFromAll(identifiedBy:)`` to unregister it.
115113
private func _addToAll() -> UInt64 {
116-
if deliverExpectationCheckedEvents, #available(_synchronizationAPI, *) {
117-
Self._deliverExpectationCheckedEventsCount.add(1, ordering: .sequentiallyConsistent)
114+
if deliverExpectationCheckedEvents {
115+
Self._deliverExpectationCheckedEventsCount.increment()
118116
}
119117
return Self._all.withLock { all in
120118
let id = all.nextID
@@ -133,8 +131,8 @@ extension Configuration {
133131
let configuration = Self._all.withLock { all in
134132
all.instances.removeValue(forKey: id)
135133
}
136-
if let configuration, configuration.deliverExpectationCheckedEvents, #available(_synchronizationAPI, *) {
137-
Self._deliverExpectationCheckedEventsCount.subtract(1, ordering: .sequentiallyConsistent)
134+
if let configuration, configuration.deliverExpectationCheckedEvents {
135+
Self._deliverExpectationCheckedEventsCount.decrement()
138136
}
139137
}
140138

@@ -143,8 +141,7 @@ extension Configuration {
143141
///
144142
/// On older Apple platforms, this property is not available and ``all`` is
145143
/// directly consulted instead (which is less efficient.)
146-
@available(_synchronizationAPI, *)
147-
private static let _deliverExpectationCheckedEventsCount = Atomic(0)
144+
private static let _deliverExpectationCheckedEventsCount = Locked(rawValue: 0)
148145

149146
/// Whether or not events of the kind
150147
/// ``Event/Kind-swift.enum/expectationChecked(_:)`` should be delivered to
@@ -155,11 +152,7 @@ extension Configuration {
155152
/// for these events, consult the per-instance
156153
/// ``Configuration/deliverExpectationCheckedEvents`` property.
157154
static var deliverExpectationCheckedEvents: Bool {
158-
if #available(_synchronizationAPI, *) {
159-
_deliverExpectationCheckedEventsCount.load(ordering: .sequentiallyConsistent) > 0
160-
} else {
161-
all.contains(where: \.deliverExpectationCheckedEvents)
162-
}
155+
_deliverExpectationCheckedEventsCount.rawValue > 0
163156
}
164157
}
165158

Sources/Testing/Support/Locked.swift

+9
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,15 @@ extension Locked where T: Numeric {
177177
@discardableResult func increment() -> T {
178178
add(1)
179179
}
180+
181+
/// Decrement the current wrapped value of this instance.
182+
///
183+
/// - Returns: The sum of ``rawValue`` and `-1`.
184+
///
185+
/// This function is exactly equivalent to `add(-1)`.
186+
@discardableResult func decrement() -> T {
187+
add(-1)
188+
}
180189
}
181190

182191
extension Locked {

cmake/modules/shared/AvailabilityDefinitions.cmake

-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,5 @@ add_compile_options(
1313
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -define-availability -Xfrontend \"_clockAPI:macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0\">"
1414
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -define-availability -Xfrontend \"_regexAPI:macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0\">"
1515
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -define-availability -Xfrontend \"_swiftVersionAPI:macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0\">"
16-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -define-availability -Xfrontend \"_synchronizationAPI:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0\">"
1716
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -define-availability -Xfrontend \"_typedThrowsAPI:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0\">"
1817
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -define-availability -Xfrontend \"_distantFuture:macOS 99.0, iOS 99.0, watchOS 99.0, tvOS 99.0, visionOS 99.0\">")

0 commit comments

Comments
 (0)