Skip to content

Commit d63a400

Browse files
authored
Address deprecation warnings (#41)
Use atomics library where possible, use swift-nio atomics in other cases
1 parent aefea3f commit d63a400

File tree

6 files changed

+129
-6
lines changed

6 files changed

+129
-6
lines changed

Package.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ let package = Package(
2525
.package(url: "https://github.com/apple/swift-metrics.git", "1.0.0" ..< "3.0.0"),
2626
.package(url: "https://github.com/apple/swift-nio.git", from: "2.0.0"),
2727
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"),
28+
.package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.0"),
2829
],
2930
targets: [
3031
.target(name: "StatsdClient", dependencies: [
3132
.product(name: "CoreMetrics", package: "swift-metrics"),
3233
.product(name: "NIO", package: "swift-nio"),
34+
.product(name: "Atomics", package: "swift-atomics"),
3335
]),
3436
.testTarget(name: "StatsdClientTests", dependencies: [
3537
.target(name: "StatsdClient"),

Package@swift-5.5.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ let package = Package(
2424
dependencies: [
2525
.package(url: "https://github.com/apple/swift-metrics.git", "1.0.0" ..< "3.0.0"),
2626
.package(url: "https://github.com/apple/swift-nio.git", from: "2.0.0"),
27+
.package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.0"),
2728
],
2829
targets: [
2930
.target(name: "StatsdClient", dependencies: ["CoreMetrics", "NIO"]),

Sources/StatsdClient/Atomics.swift

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftStatsdClient open source project
4+
//
5+
// Copyright (c) 2019-2023 the SwiftStatsdClient project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftStatsdClient project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import Foundation
16+
#if canImport(Atomics)
17+
import Atomics
18+
#else
19+
import NIOConcurrencyHelpers
20+
#endif
21+
22+
internal class AtomicCounter {
23+
#if canImport(Atomics)
24+
private let managed: ManagedAtomic<Int64>
25+
#else
26+
private let nio: NIOAtomic<Int64>
27+
#endif
28+
29+
init(_ value: Int64) {
30+
#if canImport(Atomics)
31+
self.managed = ManagedAtomic(value)
32+
#else
33+
self.nio = NIOAtomic.makeAtomic(value: value)
34+
#endif
35+
}
36+
37+
func load() -> Int64 {
38+
#if canImport(Atomics)
39+
return self.managed.load(ordering: .sequentiallyConsistent)
40+
#else
41+
return self.nio.load()
42+
#endif
43+
}
44+
45+
func compareExchange(expected: Int64, desired: Int64) -> Bool {
46+
#if canImport(Atomics)
47+
return self.managed.compareExchange(
48+
expected: expected,
49+
desired: desired,
50+
ordering: .sequentiallyConsistent
51+
).exchanged
52+
#else
53+
return self.nio.compareAndExchange(expected: expected, desired: desired)
54+
#endif
55+
}
56+
57+
func store(_ value: Int64) {
58+
#if canImport(Atomics)
59+
self.managed.store(value, ordering: .sequentiallyConsistent)
60+
#else
61+
self.nio.store(value)
62+
#endif
63+
}
64+
}
65+
66+
internal class AtomicBoolean {
67+
#if canImport(Atomics)
68+
private let managed: ManagedAtomic<Bool>
69+
#else
70+
private let nio: NIOAtomic<Bool>
71+
#endif
72+
73+
init(_ value: Bool) {
74+
#if canImport(Atomics)
75+
self.managed = ManagedAtomic(value)
76+
#else
77+
self.nio = NIOAtomic.makeAtomic(value: value)
78+
#endif
79+
}
80+
81+
func load() -> Bool {
82+
#if canImport(Atomics)
83+
return self.managed.load(ordering: .sequentiallyConsistent)
84+
#else
85+
return self.nio.load()
86+
#endif
87+
}
88+
89+
func compareExchange(expected: Bool, desired: Bool) -> Bool {
90+
#if canImport(Atomics)
91+
return self.managed.compareExchange(
92+
expected: expected,
93+
desired: desired,
94+
ordering: .sequentiallyConsistent
95+
).exchanged
96+
#else
97+
return self.nio.compareAndExchange(expected: expected, desired: desired)
98+
#endif
99+
}
100+
101+
func store(_ value: Bool) {
102+
#if canImport(Atomics)
103+
self.managed.store(value, ordering: .sequentiallyConsistent)
104+
#else
105+
self.nio.store(value)
106+
#endif
107+
}
108+
}

Sources/StatsdClient/StatsdClient.swift

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@ public final class StatsdClient: MetricsFactory {
2424
private var counters = [String: CounterHandler]() // protected by a lock
2525
private var recorders = [String: RecorderHandler]() // protected by a lock
2626
private var timers = [String: TimerHandler]() // protected by a lock
27+
#if swift(<5.5)
2728
private let lock = Lock()
28-
29+
#else
30+
private let lock = NIOLock()
31+
#endif
2932
/// Create a new instance of `StatsdClient`.
3033
///
3134
/// - Parameters:
@@ -130,7 +133,7 @@ public final class StatsdClient: MetricsFactory {
130133
private final class StatsdCounter: CounterHandler, Equatable {
131134
let id: String
132135
let client: Client
133-
var value = NIOAtomic<Int64>.makeAtomic(value: 0)
136+
var value = AtomicCounter(0)
134137

135138
init(label: String, dimensions: [(String, String)], client: Client) {
136139
self.id = StatsdUtils.id(label: label, dimensions: dimensions, sanitizer: client.metricNameSanitizer)
@@ -153,7 +156,8 @@ private final class StatsdCounter: CounterHandler, Equatable {
153156
return // already at max
154157
}
155158
let newValue = oldValue.addingReportingOverflow(amount)
156-
if self.value.compareAndExchange(expected: oldValue, desired: newValue.overflow ? Int64.max : newValue.partialValue) {
159+
160+
if self.value.compareExchange(expected: oldValue, desired: newValue.overflow ? Int64.max : newValue.partialValue) {
157161
return
158162
}
159163
}
@@ -251,10 +255,14 @@ private final class Client {
251255

252256
private let address: SocketAddress
253257

254-
private let isShutdown = NIOAtomic<Bool>.makeAtomic(value: false)
258+
private let isShutdown = AtomicBoolean(false)
255259

256260
private var state = State.disconnected
261+
#if swift(<5.5)
257262
private let lock = Lock()
263+
#else
264+
private let lock = NIOLock()
265+
#endif
258266

259267
private enum State {
260268
case disconnected
@@ -285,7 +293,7 @@ private final class Client {
285293
func shutdown(_ callback: @escaping (Error?) -> Void) {
286294
switch self.eventLoopGroupProvider {
287295
case .createNew:
288-
if self.isShutdown.compareAndExchange(expected: false, desired: true) {
296+
if self.isShutdown.compareExchange(expected: false, desired: true) {
289297
self.eventLoopGroup.shutdownGracefully(callback)
290298
}
291299
case .shared:

Tests/StatsdClientTests/StatsdClientTests.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,11 @@ class StatsdClientTests: XCTestCase {
276276
let id = UUID().uuidString
277277

278278
var results = [String]()
279+
#if swift(<5.5)
279280
let lock = Lock()
281+
#else
282+
let lock = NIOLock()
283+
#endif
280284

281285
let group = DispatchGroup()
282286
server.onData { _, data in

scripts/soundness.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
1919

2020
function replace_acceptable_years() {
2121
# this needs to replace all acceptable forms with 'YEARS'
22-
sed -e 's/20[12][901]-202[0123]/YEARS/' -e 's/2019/YEARS/' -e 's/202[012]/YEARS/'
22+
sed -e 's/20[12][901]-202[0123]/YEARS/' -e 's/2019/YEARS/' -e 's/202[0123]/YEARS/'
2323
}
2424

2525
printf "=> Checking for unacceptable language... "

0 commit comments

Comments
 (0)