Skip to content

Commit deeaea4

Browse files
committed
Adopt Mutex where available
1 parent 46dd772 commit deeaea4

File tree

1 file changed

+50
-7
lines changed

1 file changed

+50
-7
lines changed

Sources/HTTPTypes/HTTPFields.swift

+50-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
#if canImport(Synchronization)
16+
import Synchronization
17+
#endif // canImport(Synchronization)
18+
1519
/// A collection of HTTP fields. It is used in `HTTPRequest` and `HTTPResponse`, and can also be
1620
/// used as HTTP trailer fields.
1721
///
@@ -21,13 +25,19 @@
2125
/// `HTTPFields` adheres to modern HTTP semantics. In particular, the "Cookie" request header field
2226
/// is split into separate header fields by default.
2327
public struct HTTPFields: Sendable, Hashable {
24-
private final class _Storage: @unchecked Sendable, Hashable {
28+
private class _Storage: @unchecked Sendable, Hashable {
2529
var fields: [(field: HTTPField, next: UInt16)] = []
2630
var index: [String: (first: UInt16, last: UInt16)]? = [:]
27-
let lock = LockStorage.create(value: ())
31+
32+
required init() {
33+
}
34+
35+
func withLock<Result>(_ body: () throws -> Result) rethrows -> Result {
36+
fatalError()
37+
}
2838

2939
var ensureIndex: [String: (first: UInt16, last: UInt16)] {
30-
self.lock.withLockedValue { _ in
40+
self.withLock {
3141
if let index = self.index {
3242
return index
3343
}
@@ -45,10 +55,10 @@ public struct HTTPFields: Sendable, Hashable {
4555
}
4656
}
4757

48-
func copy() -> _Storage {
49-
let newStorage = _Storage()
58+
func copy() -> Self {
59+
let newStorage = Self()
5060
newStorage.fields = self.fields
51-
self.lock.withLockedValue { _ in
61+
self.withLock {
5262
newStorage.index = self.index
5363
}
5464
return newStorage
@@ -99,7 +109,40 @@ public struct HTTPFields: Sendable, Hashable {
99109
}
100110
}
101111

102-
private var _storage = _Storage()
112+
#if canImport(Synchronization)
113+
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
114+
private final class _StorageWithMutex: _Storage, @unchecked Sendable {
115+
let mutex = Mutex<Void>(())
116+
117+
override func withLock<Result>(_ body: () throws -> Result) rethrows -> Result {
118+
try self.mutex.withLock { _ in
119+
try body()
120+
}
121+
}
122+
}
123+
#endif // canImport(Synchronization)
124+
125+
private final class _StorageWithNIOLock: _Storage, @unchecked Sendable {
126+
let lock = LockStorage.create(value: ())
127+
128+
override func withLock<Result>(_ body: () throws -> Result) rethrows -> Result {
129+
try self.lock.withLockedValue { _ in
130+
try body()
131+
}
132+
}
133+
}
134+
135+
private var _storage = {
136+
#if canImport(Synchronization)
137+
if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) {
138+
_StorageWithMutex()
139+
} else {
140+
_StorageWithNIOLock()
141+
}
142+
#else // canImport(Synchronization)
143+
_StorageWithNIOLock()
144+
#endif // canImport(Synchronization)
145+
}()
103146

104147
/// Create an empty list of HTTP fields
105148
public init() {}

0 commit comments

Comments
 (0)