Skip to content

Commit 34eec3a

Browse files
committed
swift-mutex update
1 parent 8a6cb8f commit 34eec3a

File tree

4 files changed

+283
-95
lines changed

4 files changed

+283
-95
lines changed

Sources/Mutex.swift

Lines changed: 93 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@
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
97106
import func os.os_unfair_lock_unlock
98107
import 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)
135140
import Musl
141+
#elseif canImport(Bionic)
142+
import Android
136143
#else
137144
import 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 {
180184
import ucrt
181185
import 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

Comments
 (0)