@@ -31,9 +31,16 @@ import Darwin
3131import ucrt
3232import WinSDK
3333#elseif canImport(Glibc)
34- import Glibc
34+ @ preconcurrency import Glibc
3535#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
3744#else
3845#error("The concurrency NIOLock module was unable to identify your C library.")
3946#endif
@@ -47,7 +54,7 @@ typealias LockPrimitive = pthread_mutex_t
4754#endif
4855
4956@usableFromInline
50- enum LockOperations { }
57+ enum LockOperations : Sendable { }
5158
5259extension LockOperations {
5360 @inlinable
@@ -56,12 +63,15 @@ extension LockOperations {
5663
5764 #if os(Windows)
5865 InitializeSRWLock ( mutex)
59- #else
66+ #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))
6067 var attr = pthread_mutexattr_t ( )
6168 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+ )
6575
6676 let err = pthread_mutex_init ( mutex, & attr)
6777 precondition ( err == 0 , " \( #function) failed in pthread_mutex with error \( err) " )
@@ -74,7 +84,7 @@ extension LockOperations {
7484
7585 #if os(Windows)
7686 // SRWLOCK does not need to be free'd
77- #else
87+ #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))
7888 let err = pthread_mutex_destroy ( mutex)
7989 precondition ( err == 0 , " \( #function) failed in pthread_mutex with error \( err) " )
8090 #endif
@@ -86,7 +96,7 @@ extension LockOperations {
8696
8797 #if os(Windows)
8898 AcquireSRWLockExclusive ( mutex)
89- #else
99+ #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))
90100 let err = pthread_mutex_lock ( mutex)
91101 precondition ( err == 0 , " \( #function) failed in pthread_mutex with error \( err) " )
92102 #endif
@@ -98,7 +108,7 @@ extension LockOperations {
98108
99109 #if os(Windows)
100110 ReleaseSRWLockExclusive ( mutex)
101- #else
111+ #elseif (compiler(<6.1) && !os(WASI)) || (compiler(>=6.1) && _runtime(_multithreaded))
102112 let err = pthread_mutex_unlock ( mutex)
103113 precondition ( err == 0 , " \( #function) failed in pthread_mutex with error \( err) " )
104114 #endif
@@ -139,9 +149,11 @@ final class LockStorage<Value>: ManagedBuffer<Value, LockPrimitive> {
139149 @inlinable
140150 static func create( value: Value ) -> Self {
141151 let buffer = Self . create ( minimumCapacity: 1 ) { _ in
142- return value
152+ value
143153 }
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
145157 let storage = buffer as! Self
146158
147159 storage. withUnsafeMutablePointers { _, lockPtr in
@@ -175,7 +187,7 @@ final class LockStorage<Value>: ManagedBuffer<Value, LockPrimitive> {
175187 @inlinable
176188 func withLockPrimitive< T> ( _ body: ( UnsafeMutablePointer < LockPrimitive > ) throws -> T ) rethrows -> T {
177189 try self . withUnsafeMutablePointerToElements { lockPtr in
178- return try body ( lockPtr)
190+ try body ( lockPtr)
179191 }
180192 }
181193
@@ -189,11 +201,16 @@ final class LockStorage<Value>: ManagedBuffer<Value, LockPrimitive> {
189201 }
190202}
191203
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
193210
194211/// A threading lock based on `libpthread` instead of `libdispatch`.
195212///
196- /// - note : ``NIOLock`` has reference semantics.
213+ /// - Note : ``NIOLock`` has reference semantics.
197214///
198215/// This object provides a lock on top of a single `pthread_mutex_t`. This kind
199216/// of lock is safe to use with `libpthread`-based threading models, such as the
@@ -229,7 +246,7 @@ struct NIOLock {
229246
230247 @inlinable
231248 internal func withLockPrimitive< T> ( _ body: ( UnsafeMutablePointer < LockPrimitive > ) throws -> T ) rethrows -> T {
232- return try self . _storage. withLockPrimitive ( body)
249+ try self . _storage. withLockPrimitive ( body)
233250 }
234251}
235252
@@ -257,26 +274,11 @@ extension NIOLock {
257274 }
258275}
259276
260- extension NIOLock : Sendable { }
277+ extension NIOLock : @ unchecked Sendable { }
261278
262279extension UnsafeMutablePointer {
263280 @inlinable
264281 func assertValidAlignment( ) {
265282 assert ( UInt ( bitPattern: self ) % UInt( MemoryLayout< Pointee> . alignment) == 0 )
266283 }
267284}
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