@@ -31,9 +31,16 @@ import Darwin
31
31
import ucrt
32
32
import WinSDK
33
33
#elseif canImport(Glibc)
34
- import Glibc
34
+ @ preconcurrency import Glibc
35
35
#elseif canImport(Musl)
36
- import Musl
36
+ @preconcurrency import Musl
37
+ #elseif canImport(Bionic)
38
+ @preconcurrency import Bionic
39
+ #elseif canImport(WASILibc)
40
+ @preconcurrency import WASILibc
41
+ #if canImport(wasi_pthread)
42
+ import wasi_pthread
43
+ #endif
37
44
#else
38
45
#error("The concurrency NIOLock module was unable to identify your C library.")
39
46
#endif
@@ -47,7 +54,7 @@ typealias LockPrimitive = pthread_mutex_t
47
54
#endif
48
55
49
56
@usableFromInline
50
- enum LockOperations { }
57
+ enum LockOperations : Sendable { }
51
58
52
59
extension LockOperations {
53
60
@inlinable
@@ -56,12 +63,15 @@ extension LockOperations {
56
63
57
64
#if os(Windows)
58
65
InitializeSRWLock ( mutex)
59
- #else
66
+ #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))
60
67
var attr = pthread_mutexattr_t ( )
61
68
pthread_mutexattr_init ( & attr)
62
- debugOnly {
63
- pthread_mutexattr_settype ( & attr, . init( PTHREAD_MUTEX_ERRORCHECK) )
64
- }
69
+ assert (
70
+ {
71
+ pthread_mutexattr_settype ( & attr, . init( PTHREAD_MUTEX_ERRORCHECK) )
72
+ return true
73
+ } ( )
74
+ )
65
75
66
76
let err = pthread_mutex_init ( mutex, & attr)
67
77
precondition ( err == 0 , " \( #function) failed in pthread_mutex with error \( err) " )
@@ -74,7 +84,7 @@ extension LockOperations {
74
84
75
85
#if os(Windows)
76
86
// SRWLOCK does not need to be free'd
77
- #else
87
+ #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))
78
88
let err = pthread_mutex_destroy ( mutex)
79
89
precondition ( err == 0 , " \( #function) failed in pthread_mutex with error \( err) " )
80
90
#endif
@@ -86,7 +96,7 @@ extension LockOperations {
86
96
87
97
#if os(Windows)
88
98
AcquireSRWLockExclusive ( mutex)
89
- #else
99
+ #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))
90
100
let err = pthread_mutex_lock ( mutex)
91
101
precondition ( err == 0 , " \( #function) failed in pthread_mutex with error \( err) " )
92
102
#endif
@@ -98,7 +108,7 @@ extension LockOperations {
98
108
99
109
#if os(Windows)
100
110
ReleaseSRWLockExclusive ( mutex)
101
- #else
111
+ #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))
102
112
let err = pthread_mutex_unlock ( mutex)
103
113
precondition ( err == 0 , " \( #function) failed in pthread_mutex with error \( err) " )
104
114
#endif
@@ -139,9 +149,11 @@ final class LockStorage<Value>: ManagedBuffer<Value, LockPrimitive> {
139
149
@inlinable
140
150
static func create( value: Value ) -> Self {
141
151
let buffer = Self . create ( minimumCapacity: 1 ) { _ in
142
- return value
152
+ value
143
153
}
144
- // Avoid 'unsafeDowncast' as there is a miscompilation on 5.10.
154
+ // Intentionally using a force cast here to avoid a miss compiliation in 5.10.
155
+ // This is as fast as an unsafeDownCast since ManagedBuffer is inlined and the optimizer
156
+ // can eliminate the upcast/downcast pair
145
157
let storage = buffer as! Self
146
158
147
159
storage. withUnsafeMutablePointers { _, lockPtr in
@@ -175,7 +187,7 @@ final class LockStorage<Value>: ManagedBuffer<Value, LockPrimitive> {
175
187
@inlinable
176
188
func withLockPrimitive< T> ( _ body: ( UnsafeMutablePointer < LockPrimitive > ) throws -> T ) rethrows -> T {
177
189
try self . withUnsafeMutablePointerToElements { lockPtr in
178
- return try body ( lockPtr)
190
+ try body ( lockPtr)
179
191
}
180
192
}
181
193
@@ -189,11 +201,16 @@ final class LockStorage<Value>: ManagedBuffer<Value, LockPrimitive> {
189
201
}
190
202
}
191
203
192
- extension LockStorage : @unchecked Sendable { }
204
+ // This compiler guard is here becaue `ManagedBuffer` is already declaring
205
+ // Sendable unavailability after 6.1, which `LockStorage` inherits.
206
+ #if compiler(<6.2)
207
+ @available ( * , unavailable)
208
+ extension LockStorage : Sendable { }
209
+ #endif
193
210
194
211
/// A threading lock based on `libpthread` instead of `libdispatch`.
195
212
///
196
- /// - note : ``NIOLock`` has reference semantics.
213
+ /// - Note : ``NIOLock`` has reference semantics.
197
214
///
198
215
/// This object provides a lock on top of a single `pthread_mutex_t`. This kind
199
216
/// of lock is safe to use with `libpthread`-based threading models, such as the
@@ -229,7 +246,7 @@ struct NIOLock {
229
246
230
247
@inlinable
231
248
internal func withLockPrimitive< T> ( _ body: ( UnsafeMutablePointer < LockPrimitive > ) throws -> T ) rethrows -> T {
232
- return try self . _storage. withLockPrimitive ( body)
249
+ try self . _storage. withLockPrimitive ( body)
233
250
}
234
251
}
235
252
@@ -257,26 +274,11 @@ extension NIOLock {
257
274
}
258
275
}
259
276
260
- extension NIOLock : Sendable { }
277
+ extension NIOLock : @ unchecked Sendable { }
261
278
262
279
extension UnsafeMutablePointer {
263
280
@inlinable
264
281
func assertValidAlignment( ) {
265
282
assert ( UInt ( bitPattern: self ) % UInt( MemoryLayout< Pointee> . alignment) == 0 )
266
283
}
267
284
}
268
-
269
- /// A utility function that runs the body code only in debug builds, without
270
- /// emitting compiler warnings.
271
- ///
272
- /// This is currently the only way to do this in Swift: see
273
- /// https://forums.swift.org/t/support-debug-only-code/11037 for a discussion.
274
- @inlinable
275
- internal func debugOnly( _ body: ( ) -> Void ) {
276
- assert (
277
- {
278
- body ( )
279
- return true
280
- } ( )
281
- )
282
- }
0 commit comments