Skip to content

Commit 68c28b2

Browse files
committed
Fix some more Sendable warnings
1 parent 649561e commit 68c28b2

File tree

4 files changed

+86
-35
lines changed

4 files changed

+86
-35
lines changed

Diff for: Sources/ConnectionPoolModule/NIOLock.swift

+35-25
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ import WinSDK
2424
import Glibc
2525
#elseif canImport(Musl)
2626
import Musl
27+
#elseif canImport(Bionic)
28+
import Bionic
29+
#elseif canImport(WASILibc)
30+
import WASILibc
31+
#if canImport(wasi_pthread)
32+
import wasi_pthread
33+
#endif
2734
#else
2835
#error("The concurrency NIOLock module was unable to identify your C library.")
2936
#endif
@@ -37,16 +44,16 @@ typealias LockPrimitive = pthread_mutex_t
3744
#endif
3845

3946
@usableFromInline
40-
enum LockOperations { }
47+
enum LockOperations {}
4148

4249
extension LockOperations {
4350
@inlinable
4451
static func create(_ mutex: UnsafeMutablePointer<LockPrimitive>) {
4552
mutex.assertValidAlignment()
4653

47-
#if os(Windows)
54+
#if os(Windows)
4855
InitializeSRWLock(mutex)
49-
#else
56+
#elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))
5057
var attr = pthread_mutexattr_t()
5158
pthread_mutexattr_init(&attr)
5259
debugOnly {
@@ -55,43 +62,43 @@ extension LockOperations {
5562

5663
let err = pthread_mutex_init(mutex, &attr)
5764
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)")
58-
#endif
65+
#endif
5966
}
6067

6168
@inlinable
6269
static func destroy(_ mutex: UnsafeMutablePointer<LockPrimitive>) {
6370
mutex.assertValidAlignment()
6471

65-
#if os(Windows)
72+
#if os(Windows)
6673
// SRWLOCK does not need to be free'd
67-
#else
74+
#elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))
6875
let err = pthread_mutex_destroy(mutex)
6976
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)")
70-
#endif
77+
#endif
7178
}
7279

7380
@inlinable
7481
static func lock(_ mutex: UnsafeMutablePointer<LockPrimitive>) {
7582
mutex.assertValidAlignment()
7683

77-
#if os(Windows)
84+
#if os(Windows)
7885
AcquireSRWLockExclusive(mutex)
79-
#else
86+
#elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))
8087
let err = pthread_mutex_lock(mutex)
8188
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)")
82-
#endif
89+
#endif
8390
}
8491

8592
@inlinable
8693
static func unlock(_ mutex: UnsafeMutablePointer<LockPrimitive>) {
8794
mutex.assertValidAlignment()
8895

89-
#if os(Windows)
96+
#if os(Windows)
9097
ReleaseSRWLockExclusive(mutex)
91-
#else
98+
#elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))
9299
let err = pthread_mutex_unlock(mutex)
93100
precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)")
94-
#endif
101+
#endif
95102
}
96103
}
97104

@@ -129,9 +136,11 @@ final class LockStorage<Value>: ManagedBuffer<Value, LockPrimitive> {
129136
@inlinable
130137
static func create(value: Value) -> Self {
131138
let buffer = Self.create(minimumCapacity: 1) { _ in
132-
return value
139+
value
133140
}
134-
// Avoid 'unsafeDowncast' as there is a miscompilation on 5.10.
141+
// Intentionally using a force cast here to avoid a miss compiliation in 5.10.
142+
// This is as fast as an unsafeDownCast since ManagedBuffer is inlined and the optimizer
143+
// can eliminate the upcast/downcast pair
135144
let storage = buffer as! Self
136145

137146
storage.withUnsafeMutablePointers { _, lockPtr in
@@ -165,7 +174,7 @@ final class LockStorage<Value>: ManagedBuffer<Value, LockPrimitive> {
165174
@inlinable
166175
func withLockPrimitive<T>(_ body: (UnsafeMutablePointer<LockPrimitive>) throws -> T) rethrows -> T {
167176
try self.withUnsafeMutablePointerToElements { lockPtr in
168-
return try body(lockPtr)
177+
try body(lockPtr)
169178
}
170179
}
171180

@@ -179,17 +188,14 @@ final class LockStorage<Value>: ManagedBuffer<Value, LockPrimitive> {
179188
}
180189
}
181190

182-
extension LockStorage: @unchecked Sendable { }
183-
184191
/// A threading lock based on `libpthread` instead of `libdispatch`.
185192
///
186-
/// - note: ``NIOLock`` has reference semantics.
193+
/// - Note: ``NIOLock`` has reference semantics.
187194
///
188195
/// This object provides a lock on top of a single `pthread_mutex_t`. This kind
189196
/// of lock is safe to use with `libpthread`-based threading models, such as the
190197
/// one used by NIO. On Windows, the lock is based on the substantially similar
191198
/// `SRWLOCK` type.
192-
@usableFromInline
193199
struct NIOLock {
194200
@usableFromInline
195201
internal let _storage: LockStorage<Void>
@@ -220,7 +226,7 @@ struct NIOLock {
220226

221227
@inlinable
222228
internal func withLockPrimitive<T>(_ body: (UnsafeMutablePointer<LockPrimitive>) throws -> T) rethrows -> T {
223-
return try self._storage.withLockPrimitive(body)
229+
try self._storage.withLockPrimitive(body)
224230
}
225231
}
226232

@@ -243,12 +249,12 @@ extension NIOLock {
243249
}
244250

245251
@inlinable
246-
func withLockVoid(_ body: () throws -> Void) rethrows -> Void {
252+
func withLockVoid(_ body: () throws -> Void) rethrows {
247253
try self.withLock(body)
248254
}
249255
}
250256

251-
extension NIOLock: Sendable {}
257+
extension NIOLock: @unchecked Sendable {}
252258

253259
extension UnsafeMutablePointer {
254260
@inlinable
@@ -264,6 +270,10 @@ extension UnsafeMutablePointer {
264270
/// https://forums.swift.org/t/support-debug-only-code/11037 for a discussion.
265271
@inlinable
266272
internal func debugOnly(_ body: () -> Void) {
267-
// FIXME: duplicated with NIO.
268-
assert({ body(); return true }())
273+
assert(
274+
{
275+
body()
276+
return true
277+
}()
278+
)
269279
}

Diff for: Sources/ConnectionPoolModule/NIOLockedValueBox.swift

+43-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
/// Provides locked access to `Value`.
1919
///
20-
/// - note: ``NIOLockedValueBox`` has reference semantics and holds the `Value`
20+
/// - Note: ``NIOLockedValueBox`` has reference semantics and holds the `Value`
2121
/// alongside a lock behind a reference.
2222
///
2323
/// This is no different than creating a ``Lock`` and protecting all
@@ -39,8 +39,48 @@ struct NIOLockedValueBox<Value> {
3939
/// Access the `Value`, allowing mutation of it.
4040
@inlinable
4141
func withLockedValue<T>(_ mutate: (inout Value) throws -> T) rethrows -> T {
42-
return try self._storage.withLockedValue(mutate)
42+
try self._storage.withLockedValue(mutate)
43+
}
44+
45+
/// Provides an unsafe view over the lock and its value.
46+
///
47+
/// This can be beneficial when you require fine grained control over the lock in some
48+
/// situations but don't want lose the benefits of ``withLockedValue(_:)`` in others by
49+
/// switching to ``NIOLock``.
50+
var unsafe: Unsafe {
51+
Unsafe(_storage: self._storage)
52+
}
53+
54+
/// Provides an unsafe view over the lock and its value.
55+
struct Unsafe {
56+
@usableFromInline
57+
let _storage: LockStorage<Value>
58+
59+
/// Manually acquire the lock.
60+
@inlinable
61+
func lock() {
62+
self._storage.lock()
63+
}
64+
65+
/// Manually release the lock.
66+
@inlinable
67+
func unlock() {
68+
self._storage.unlock()
69+
}
70+
71+
/// Mutate the value, assuming the lock has been acquired manually.
72+
///
73+
/// - Parameter mutate: A closure with scoped access to the value.
74+
/// - Returns: The result of the `mutate` closure.
75+
@inlinable
76+
func withValueAssumingLockIsAcquired<Result>(
77+
_ mutate: (_ value: inout Value) throws -> Result
78+
) rethrows -> Result {
79+
try self._storage.withUnsafeMutablePointerToHeader { value in
80+
try mutate(&value.pointee)
81+
}
82+
}
4383
}
4484
}
4585

46-
extension NIOLockedValueBox: Sendable where Value: Sendable {}
86+
extension NIOLockedValueBox: @unchecked Sendable where Value: Sendable {}

Diff for: Sources/PostgresNIO/New/PSQLTask.swift

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Logging
22
import NIOCore
33

4-
enum HandlerTask {
4+
enum HandlerTask: Sendable {
55
case extendedQuery(ExtendedQueryContext)
66
case closeCommand(CloseCommandContext)
77
case startListening(NotificationListener)
@@ -31,7 +31,7 @@ enum PSQLTask {
3131
}
3232
}
3333

34-
final class ExtendedQueryContext {
34+
final class ExtendedQueryContext: Sendable {
3535
enum Query {
3636
case unnamed(PostgresQuery, EventLoopPromise<PSQLRowStream>)
3737
case executeStatement(PSQLExecuteStatement, EventLoopPromise<PSQLRowStream>)
@@ -100,14 +100,15 @@ final class PreparedStatementContext: Sendable {
100100
}
101101
}
102102

103-
final class CloseCommandContext {
103+
final class CloseCommandContext: Sendable {
104104
let target: CloseTarget
105105
let logger: Logger
106106
let promise: EventLoopPromise<Void>
107107

108-
init(target: CloseTarget,
109-
logger: Logger,
110-
promise: EventLoopPromise<Void>
108+
init(
109+
target: CloseTarget,
110+
logger: Logger,
111+
promise: EventLoopPromise<Void>
111112
) {
112113
self.target = target
113114
self.logger = logger

Diff for: Sources/PostgresNIO/PostgresDatabase+Query.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ extension PostgresDatabase {
4040
}
4141
}
4242

43-
public struct PostgresQueryResult {
43+
public struct PostgresQueryResult: Sendable {
4444
public let metadata: PostgresQueryMetadata
4545
public let rows: [PostgresRow]
4646
}

0 commit comments

Comments
 (0)