Skip to content

Commit

Permalink
Don't use Synchronization.Atomic for `deliverExpectationCheckedEven…
Browse files Browse the repository at this point in the history
…ts`. (#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.
  • Loading branch information
grynspan authored Sep 6, 2024
1 parent ca51589 commit 2e9df4f
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 15 deletions.
1 change: 0 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ extension Array where Element == PackageDescription.SwiftSetting {
.enableExperimentalFeature("AvailabilityMacro=_clockAPI:macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0"),
.enableExperimentalFeature("AvailabilityMacro=_regexAPI:macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0"),
.enableExperimentalFeature("AvailabilityMacro=_swiftVersionAPI:macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0"),
.enableExperimentalFeature("AvailabilityMacro=_synchronizationAPI:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0"),
.enableExperimentalFeature("AvailabilityMacro=_typedThrowsAPI:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0"),

.enableExperimentalFeature("AvailabilityMacro=_distantFuture:macOS 99.0, iOS 99.0, watchOS 99.0, tvOS 99.0, visionOS 99.0"),
Expand Down
19 changes: 6 additions & 13 deletions Sources/Testing/Running/Runner.RuntimeState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
//

private import Synchronization

extension Runner {
/// A type which collects the task-scoped runtime state for a running
/// ``Runner`` instance, the tests it runs, and other objects it interacts
Expand Down Expand Up @@ -113,8 +111,8 @@ extension Configuration {
/// - Returns: A unique number identifying `self` that can be
/// passed to `_removeFromAll(identifiedBy:)`` to unregister it.
private func _addToAll() -> UInt64 {
if deliverExpectationCheckedEvents, #available(_synchronizationAPI, *) {
Self._deliverExpectationCheckedEventsCount.add(1, ordering: .sequentiallyConsistent)
if deliverExpectationCheckedEvents {
Self._deliverExpectationCheckedEventsCount.increment()
}
return Self._all.withLock { all in
let id = all.nextID
Expand All @@ -133,8 +131,8 @@ extension Configuration {
let configuration = Self._all.withLock { all in
all.instances.removeValue(forKey: id)
}
if let configuration, configuration.deliverExpectationCheckedEvents, #available(_synchronizationAPI, *) {
Self._deliverExpectationCheckedEventsCount.subtract(1, ordering: .sequentiallyConsistent)
if let configuration, configuration.deliverExpectationCheckedEvents {
Self._deliverExpectationCheckedEventsCount.decrement()
}
}

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

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

Expand Down
9 changes: 9 additions & 0 deletions Sources/Testing/Support/Locked.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,15 @@ extension Locked where T: Numeric {
@discardableResult func increment() -> T {
add(1)
}

/// Decrement the current wrapped value of this instance.
///
/// - Returns: The sum of ``rawValue`` and `-1`.
///
/// This function is exactly equivalent to `add(-1)`.
@discardableResult func decrement() -> T {
add(-1)
}
}

extension Locked {
Expand Down
1 change: 0 additions & 1 deletion cmake/modules/shared/AvailabilityDefinitions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@ add_compile_options(
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -define-availability -Xfrontend \"_clockAPI:macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0\">"
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -define-availability -Xfrontend \"_regexAPI:macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0\">"
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -define-availability -Xfrontend \"_swiftVersionAPI:macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0\">"
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -define-availability -Xfrontend \"_synchronizationAPI:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0\">"
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -define-availability -Xfrontend \"_typedThrowsAPI:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0\">"
"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 comments on commit 2e9df4f

Please sign in to comment.