2929// SOFTWARE.
3030//
3131
32- // Backports the Swift 6.0 Mutex API
33- @usableFromInline
34- package struct Mutex < Value> : @unchecked Sendable {
35- let storage : Storage
36- }
37-
3832#if compiler(>=6)
39- package extension Mutex {
33+
34+ #if !canImport(WinSDK)
35+
36+ // Backports the Swift 6 type Mutex<Value> to all Darwin platforms
37+ @usableFromInline
38+ struct Mutex < Value: ~ Copyable> : ~ Copyable {
39+ let storage : Storage < Value >
4040
4141 @usableFromInline
4242 init ( _ initialValue: consuming sending Value) {
@@ -53,40 +53,49 @@ package extension Mutex {
5353 }
5454
5555 @usableFromInline
56- borrowing func withLockIfAvailable< Result, E> (
56+ borrowing func withLockIfAvailable< Result, E: Error > (
5757 _ body: ( inout sending Value) throws ( E ) -> sending Result
58- ) throws ( E) -> sending Result? where E : Error {
58+ ) throws ( E) -> sending Result? {
5959 guard storage. tryLock ( ) else { return nil }
6060 defer { storage. unlock ( ) }
6161 return try body ( & storage. value)
6262 }
6363}
64+
65+ extension Mutex : @unchecked Sendable where Value: ~ Copyable { }
66+
6467#else
65- package extension Mutex {
68+
69+ // Windows doesn't support ~Copyable yet
70+
71+ @usableFromInline
72+ struct Mutex < Value> : @unchecked Sendable {
73+ let storage : Storage < Value >
6674
6775 @usableFromInline
68- init ( _ initialValue: Value ) {
76+ init ( _ initialValue: consuming sending Value) {
6977 self . storage = Storage ( initialValue)
7078 }
7179
7280 @usableFromInline
73- borrowing func withLock< Result> (
74- _ body: ( inout Value ) throws -> Result
75- ) rethrows -> Result {
81+ borrowing func withLock< Result, E : Error > (
82+ _ body: ( inout sending Value) throws ( E ) -> sending Result
83+ ) throws ( E ) -> sending Result {
7684 storage. lock ( )
7785 defer { storage. unlock ( ) }
7886 return try body ( & storage. value)
7987 }
8088
8189 @usableFromInline
82- borrowing func withLockIfAvailable< Result> (
83- _ body: ( inout Value ) throws -> Result
84- ) rethrows -> Result ? {
90+ borrowing func withLockIfAvailable< Result, E : Error > (
91+ _ body: ( inout sending Value) throws ( E ) -> sending Result
92+ ) throws ( E ) -> sending Result? {
8593 guard storage. tryLock ( ) else { return nil }
8694 defer { storage. unlock ( ) }
8795 return try body ( & storage. value)
8896 }
8997}
98+
9099#endif
91100
92101#if canImport(Darwin)
@@ -97,81 +106,76 @@ import func os.os_unfair_lock_lock
97106import func os. os_unfair_lock_unlock
98107import func os. os_unfair_lock_trylock
99108
100- extension Mutex {
109+ final class Storage < Value: ~ Copyable> {
110+ private let _lock : os_unfair_lock_t
111+ var value : Value
101112
102- final class Storage {
103- private let _lock : os_unfair_lock_t
104-
105- var value : Value
106-
107- init ( _ initialValue: Value ) {
108- self . _lock = . allocate( capacity: 1 )
109- self . _lock. initialize ( to: os_unfair_lock ( ) )
110- self . value = initialValue
111- }
113+ init ( _ initialValue: consuming Value ) {
114+ self . _lock = . allocate( capacity: 1 )
115+ self . _lock. initialize ( to: os_unfair_lock ( ) )
116+ self . value = initialValue
117+ }
112118
113- func lock( ) {
114- os_unfair_lock_lock ( _lock)
115- }
119+ func lock( ) {
120+ os_unfair_lock_lock ( _lock)
121+ }
116122
117- func unlock( ) {
118- os_unfair_lock_unlock ( _lock)
119- }
123+ func unlock( ) {
124+ os_unfair_lock_unlock ( _lock)
125+ }
120126
121- func tryLock( ) -> Bool {
122- os_unfair_lock_trylock ( _lock)
123- }
127+ func tryLock( ) -> Bool {
128+ os_unfair_lock_trylock ( _lock)
129+ }
124130
125- deinit {
126- self . _lock. deinitialize ( count: 1 )
127- self . _lock. deallocate ( )
128- }
131+ deinit {
132+ self . _lock. deinitialize ( count: 1 )
133+ self . _lock. deallocate ( )
129134 }
130135}
131136
132- #elseif canImport(Glibc) || canImport(Musl)
137+ #elseif canImport(Glibc) || canImport(Musl) || canImport(Bionic)
133138
134139#if canImport(Musl)
135140import Musl
141+ #elseif canImport(Bionic)
142+ import Android
136143#else
137144import Glibc
138145#endif
139146
140- extension Mutex {
141-
142- final class Storage {
143- private let _lock : UnsafeMutablePointer < pthread_mutex_t >
147+ final class Storage < Value: ~ Copyable> {
148+ private let _lock : UnsafeMutablePointer < pthread_mutex_t >
144149
145- var value : Value
150+ var value : Value
146151
147- init ( _ initialValue: Value ) {
148- var attr = pthread_mutexattr_t ( )
149- pthread_mutexattr_init ( & attr)
150- self . _lock = . allocate( capacity: 1 )
151- let err = pthread_mutex_init ( self . _lock, & attr)
152- precondition ( err == 0 , " pthread_mutex_init error: \( err) " )
153- self . value = initialValue
154- }
152+ init ( _ initialValue: consuming Value ) {
153+ var attr = pthread_mutexattr_t ( )
154+ pthread_mutexattr_init ( & attr)
155+ self . _lock = . allocate( capacity: 1 )
156+ let err = pthread_mutex_init ( self . _lock, & attr)
157+ precondition ( err == 0 , " pthread_mutex_init error: \( err) " )
158+ self . value = initialValue
159+ }
155160
156- func lock( ) {
157- let err = pthread_mutex_lock ( _lock)
158- precondition ( err == 0 , " pthread_mutex_lock error: \( err) " )
159- }
161+ func lock( ) {
162+ let err = pthread_mutex_lock ( _lock)
163+ precondition ( err == 0 , " pthread_mutex_lock error: \( err) " )
164+ }
160165
161- func unlock( ) {
162- let err = pthread_mutex_unlock ( _lock)
163- precondition ( err == 0 , " pthread_mutex_unlock error: \( err) " )
164- }
166+ func unlock( ) {
167+ let err = pthread_mutex_unlock ( _lock)
168+ precondition ( err == 0 , " pthread_mutex_unlock error: \( err) " )
169+ }
165170
166- func tryLock( ) -> Bool {
167- pthread_mutex_trylock ( _lock) == 0
168- }
171+ func tryLock( ) -> Bool {
172+ pthread_mutex_trylock ( _lock) == 0
173+ }
169174
170- deinit {
171- let err = pthread_mutex_destroy ( self . _lock)
172- precondition ( err == 0 , " pthread_mutex_destroy error: \( err) " )
173- self . _lock. deallocate ( )
174- }
175+ deinit {
176+ let err = pthread_mutex_destroy ( self . _lock)
177+ precondition ( err == 0 , " pthread_mutex_destroy error: \( err) " )
178+ self . _lock. deallocate ( )
175179 }
176180}
177181
@@ -180,31 +184,30 @@ extension Mutex {
180184import ucrt
181185import WinSDK
182186
183- extension Mutex {
184-
185- final class Storage {
186- private let _lock : UnsafeMutablePointer < SRWLOCK >
187+ final class Storage < Value> {
188+ private let _lock : UnsafeMutablePointer < SRWLOCK >
187189
188- var value : Value
190+ var value : Value
189191
190- init ( _ initialValue: Value ) {
191- self . _lock = . allocate( capacity: 1 )
192- InitializeSRWLock ( self . _lock)
193- self . value = initialValue
194- }
192+ init ( _ initialValue: Value ) {
193+ self . _lock = . allocate( capacity: 1 )
194+ InitializeSRWLock ( self . _lock)
195+ self . value = initialValue
196+ }
195197
196- func lock( ) {
197- AcquireSRWLockExclusive ( _lock)
198- }
198+ func lock( ) {
199+ AcquireSRWLockExclusive ( _lock)
200+ }
199201
200- func unlock( ) {
201- ReleaseSRWLockExclusive ( _lock)
202- }
202+ func unlock( ) {
203+ ReleaseSRWLockExclusive ( _lock)
204+ }
203205
204- func tryLock( ) -> Bool {
205- TryAcquireSRWLockExclusive ( _lock) != 0
206- }
206+ func tryLock( ) -> Bool {
207+ TryAcquireSRWLockExclusive ( _lock) != 0
207208 }
208209}
209210
210211#endif
212+
213+ #endif
0 commit comments