From a995fa637740fea7804a7452542ef3db184cf405 Mon Sep 17 00:00:00 2001 From: Xander Deng Date: Wed, 30 Jun 2021 16:33:27 +0800 Subject: [PATCH] adopt swift-atomics --- Package.resolved | 9 +++++++++ Package.swift | 3 +++ Package@swift-5.2.swift | 12 +++++++++-- Sources/CXTestUtility/Common.swift | 8 ++++++++ Sources/CombineX/CombineIdentifier.swift | 10 +++++++++- .../CombineXTests/CombineIdentifierSpec.swift | 20 +++++++++++++++++++ 6 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 Sources/CXTestUtility/Common.swift diff --git a/Package.resolved b/Package.resolved index 8d1e7e2e..8bead854 100644 --- a/Package.resolved +++ b/Package.resolved @@ -45,6 +45,15 @@ "revision": "6094e6f23a02b52b5d211fd114a4750c4f3ecef3", "version": "0.2.1" } + }, + { + "package": "swift-atomics", + "repositoryURL": "https://github.com/apple/swift-atomics.git", + "state": { + "branch": null, + "revision": "3e95ba32cd1b4c877f6163e8eea54afc4e63bf9f", + "version": "0.0.3" + } } ] }, diff --git a/Package.swift b/Package.swift index 9272ef40..d7846a93 100644 --- a/Package.swift +++ b/Package.swift @@ -7,6 +7,9 @@ let package = Package( products: [ .library(name: "CombineX", targets: ["CombineX", "CXFoundation"]), ], + dependencies: [ + // TODO: use swift-atomics which requires swift 5.1 + ], targets: [ .target(name: "CXUtility"), .target(name: "CombineX", dependencies: ["CXUtility"]), diff --git a/Package@swift-5.2.swift b/Package@swift-5.2.swift index 39a49557..0ce15b94 100644 --- a/Package@swift-5.2.swift +++ b/Package@swift-5.2.swift @@ -15,14 +15,22 @@ let package = Package( .library(name: "CombineX", targets: ["CombineX", "CXFoundation"]), ], dependencies: [ + .package(url: "https://github.com/apple/swift-atomics.git", .upToNextMinor(from: "0.0.3")), .package(url: "https://github.com/Quick/Quick.git", from: "3.0.0"), .package(url: "https://github.com/Quick/Nimble.git", from: "9.0.0"), .package(url: "https://github.com/ddddxxx/Semver.git", .upToNextMinor(from: "0.2.1")), ], targets: [ .target(name: "CXUtility"), - .target(name: "CombineX", dependencies: ["CXUtility"]), - .target(name: "CXFoundation", dependencies: ["CXUtility", "CombineX"]), + .target( + name: "CombineX", + dependencies: [ + "CXUtility", + .product(name: "Atomics", package: "swift-atomics")], + swiftSettings: [.define("CX_LOCK_FREE_ATOMIC")]), + .target( + name: "CXFoundation", + dependencies: ["CXUtility", "CombineX"]), // We have circular dependency CombineXTests -> CXTest -> CXShim -> CombineX // diff --git a/Sources/CXTestUtility/Common.swift b/Sources/CXTestUtility/Common.swift new file mode 100644 index 00000000..0e5db7ac --- /dev/null +++ b/Sources/CXTestUtility/Common.swift @@ -0,0 +1,8 @@ +@inline(never) +public func blackHole(_ x: T) { +} + +@inline(never) +public func identity(_ x: T) -> T { + return x +} diff --git a/Sources/CombineX/CombineIdentifier.swift b/Sources/CombineX/CombineIdentifier.swift index dfe36966..a10ea9b0 100644 --- a/Sources/CombineX/CombineIdentifier.swift +++ b/Sources/CombineX/CombineIdentifier.swift @@ -1,15 +1,23 @@ +#if CX_LOCK_FREE_ATOMIC +@_implementationOnly import Atomics +private let counter = UnsafeAtomic.create(0) +#else #if !COCOAPODS import CXUtility #endif - private let counter = LockedAtomic(0) +#endif public struct CombineIdentifier: Hashable, CustomStringConvertible { private let value: UInt64 public init() { + #if CX_LOCK_FREE_ATOMIC + self.value = counter.loadThenWrappingIncrement(ordering: .relaxed) + #else self.value = counter.loadThenWrappingIncrement() + #endif } public init(_ obj: AnyObject) { diff --git a/Tests/CombineXTests/CombineIdentifierSpec.swift b/Tests/CombineXTests/CombineIdentifierSpec.swift index c2e065bb..d1b8a8ea 100644 --- a/Tests/CombineXTests/CombineIdentifierSpec.swift +++ b/Tests/CombineXTests/CombineIdentifierSpec.swift @@ -39,3 +39,23 @@ class CombineIdentifierSpec: QuickSpec { } } } + +import XCTest + +class CombineIdentifierTests: XCTestCase { + + func testPerformance() { + measure { + let g = DispatchGroup() + for _ in 0..<1000 { + DispatchQueue.global().async(group: g) { + for _ in 0..<1000 { + blackHole(CombineIdentifier()) + } + } + } + g.wait() + } + } +} +