Skip to content

Commit

Permalink
Merge pull request #70 from guoye-zhang/mutex
Browse files Browse the repository at this point in the history
Adopt Mutex where available
  • Loading branch information
guoye-zhang authored Nov 13, 2024
2 parents 4f278a0 + e44a816 commit 7e038be
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"mallocCountTotal" : 14
"mallocCountTotal" : 13
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"mallocCountTotal" : 14
"mallocCountTotal" : 13
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"mallocCountTotal" : 14
"mallocCountTotal" : 13
}
57 changes: 50 additions & 7 deletions Sources/HTTPTypes/HTTPFields.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
//
//===----------------------------------------------------------------------===//

#if compiler(>=6.0)
import Synchronization
#endif // compiler(>=6.0)

/// A collection of HTTP fields. It is used in `HTTPRequest` and `HTTPResponse`, and can also be
/// used as HTTP trailer fields.
///
Expand All @@ -21,13 +25,19 @@
/// `HTTPFields` adheres to modern HTTP semantics. In particular, the "Cookie" request header field
/// is split into separate header fields by default.
public struct HTTPFields: Sendable, Hashable {
private final class _Storage: @unchecked Sendable, Hashable {
private class _Storage: @unchecked Sendable, Hashable {
var fields: [(field: HTTPField, next: UInt16)] = []
var index: [String: (first: UInt16, last: UInt16)]? = [:]
let lock = LockStorage.create(value: ())

required init() {
}

func withLock<Result>(_ body: () throws -> Result) rethrows -> Result {
fatalError()
}

var ensureIndex: [String: (first: UInt16, last: UInt16)] {
self.lock.withLockedValue { _ in
self.withLock {
if let index = self.index {
return index
}
Expand All @@ -45,10 +55,10 @@ public struct HTTPFields: Sendable, Hashable {
}
}

func copy() -> _Storage {
let newStorage = _Storage()
func copy() -> Self {
let newStorage = Self()
newStorage.fields = self.fields
self.lock.withLockedValue { _ in
self.withLock {
newStorage.index = self.index
}
return newStorage
Expand Down Expand Up @@ -99,7 +109,40 @@ public struct HTTPFields: Sendable, Hashable {
}
}

private var _storage = _Storage()
#if compiler(>=6.0)
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
private final class _StorageWithMutex: _Storage, @unchecked Sendable {
let mutex = Mutex<Void>(())

override func withLock<Result>(_ body: () throws -> Result) rethrows -> Result {
try self.mutex.withLock { _ in
try body()
}
}
}
#endif // compiler(>=6.0)

private final class _StorageWithNIOLock: _Storage, @unchecked Sendable {
let lock = LockStorage.create(value: ())

override func withLock<Result>(_ body: () throws -> Result) rethrows -> Result {
try self.lock.withLockedValue { _ in
try body()
}
}
}

private var _storage = {
#if compiler(>=6.0)
if #available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) {
_StorageWithMutex()
} else {
_StorageWithNIOLock()
}
#else // compiler(>=6.0)
_StorageWithNIOLock()
#endif // compiler(>=6.0)
}()

/// Create an empty list of HTTP fields
public init() {}
Expand Down

0 comments on commit 7e038be

Please sign in to comment.