29
29
// SOFTWARE.
30
30
//
31
31
32
- // Backports the Swift interface around os_unfair_lock_t available in recent Darwin platforms
33
- //
32
+ // Backports the Swift interface around OSAllocatedUnfairLock available in recent Darwin platforms
34
33
public struct AllocatedLock < State> : @unchecked Sendable {
35
34
36
35
@usableFromInline
37
36
let storage : Storage
38
37
39
- public init ( initialState: State ) {
38
+ public init ( uncheckedState initialState: State ) {
39
+ self . storage = Storage ( initialState: initialState)
40
+ }
41
+
42
+ public init ( initialState: State ) where State: Sendable {
40
43
self . storage = Storage ( initialState: initialState)
41
44
}
42
45
@@ -46,6 +49,28 @@ public struct AllocatedLock<State>: @unchecked Sendable {
46
49
defer { storage. unlock ( ) }
47
50
return try body ( & storage. state)
48
51
}
52
+
53
+ @inlinable
54
+ public func withLockIfAvailable< R> ( _ body: @Sendable ( inout State ) throws -> R ) rethrows -> R ? where R: Sendable {
55
+ guard storage. tryLock ( ) else { return nil }
56
+ defer { storage. unlock ( ) }
57
+ return try body ( & storage. state)
58
+ }
59
+
60
+ @inlinable
61
+ public func withLockIfAvailableUnchecked< R> ( _ body: ( inout State ) throws -> R ) rethrows -> R ? {
62
+ guard storage. tryLock ( ) else { return nil }
63
+ defer { storage. unlock ( ) }
64
+ return try body ( & storage. state)
65
+ }
66
+
67
+ @inlinable
68
+ public func withLockUnchecked< R> ( _ body: ( inout State ) throws -> R ) rethrows -> R {
69
+ storage. lock ( )
70
+ defer { storage. unlock ( ) }
71
+ return try body ( & storage. state)
72
+ }
73
+
49
74
}
50
75
51
76
public extension AllocatedLock where State == Void {
@@ -59,6 +84,11 @@ public extension AllocatedLock where State == Void {
59
84
storage. lock ( )
60
85
}
61
86
87
+ @inlinable @available ( * , noasync)
88
+ func lockIfAvailable( ) -> Bool {
89
+ storage. tryLock ( )
90
+ }
91
+
62
92
@inlinable @available ( * , noasync)
63
93
func unlock( ) {
64
94
storage. unlock ( )
@@ -70,6 +100,27 @@ public extension AllocatedLock where State == Void {
70
100
defer { storage. unlock ( ) }
71
101
return try body ( )
72
102
}
103
+
104
+ @inlinable
105
+ func withLockIfAvailable< R> ( _ body: @Sendable ( ) throws -> R ) rethrows -> R ? where R: Sendable {
106
+ guard storage. tryLock ( ) else { return nil }
107
+ defer { storage. unlock ( ) }
108
+ return try body ( )
109
+ }
110
+
111
+ @inlinable
112
+ func withLockIfAvailableUnchecked< R> ( _ body: ( ) throws -> R ) rethrows -> R ? {
113
+ guard storage. tryLock ( ) else { return nil }
114
+ defer { storage. unlock ( ) }
115
+ return try body ( )
116
+ }
117
+
118
+ @inlinable
119
+ func withLockUnchecked< R> ( _ body: ( ) throws -> R ) rethrows -> R {
120
+ storage. lock ( )
121
+ defer { storage. unlock ( ) }
122
+ return try body ( )
123
+ }
73
124
}
74
125
75
126
#if canImport(Darwin)
@@ -78,6 +129,7 @@ import struct os.os_unfair_lock_t
78
129
import struct os. os_unfair_lock
79
130
import func os. os_unfair_lock_lock
80
131
import func os. os_unfair_lock_unlock
132
+ import func os. os_unfair_lock_trylock
81
133
82
134
extension AllocatedLock {
83
135
@usableFromInline
@@ -103,6 +155,11 @@ extension AllocatedLock {
103
155
os_unfair_lock_unlock ( _lock)
104
156
}
105
157
158
+ @usableFromInline
159
+ func tryLock( ) -> Bool {
160
+ os_unfair_lock_trylock ( _lock)
161
+ }
162
+
106
163
deinit {
107
164
self . _lock. deinitialize ( count: 1 )
108
165
self . _lock. deallocate ( )
@@ -112,7 +169,7 @@ extension AllocatedLock {
112
169
113
170
#elseif canImport(Glibc)
114
171
115
- @ _implementationOnly import Glibc
172
+ import Glibc
116
173
117
174
extension AllocatedLock {
118
175
@usableFromInline
@@ -143,6 +200,11 @@ extension AllocatedLock {
143
200
precondition ( err == 0 , " pthread_mutex_unlock error: \( err) " )
144
201
}
145
202
203
+ @usableFromInline
204
+ func tryLock( ) -> Bool {
205
+ pthread_mutex_trylock ( _lock) == 0
206
+ }
207
+
146
208
deinit {
147
209
let err = pthread_mutex_destroy ( self . _lock)
148
210
precondition ( err == 0 , " pthread_mutex_destroy error: \( err) " )
@@ -153,8 +215,8 @@ extension AllocatedLock {
153
215
154
216
#elseif canImport(WinSDK)
155
217
156
- @ _implementationOnly import ucrt
157
- @ _implementationOnly import WinSDK
218
+ import ucrt
219
+ import WinSDK
158
220
159
221
extension AllocatedLock {
160
222
@usableFromInline
@@ -179,6 +241,17 @@ extension AllocatedLock {
179
241
func unlock( ) {
180
242
ReleaseSRWLockExclusive ( _lock)
181
243
}
244
+
245
+ @usableFromInline
246
+ func tryLock( ) -> Bool {
247
+ TryAcquireSRWLockExclusive ( _lock)
248
+ }
249
+
250
+ @usableFromInline
251
+ func tryLock( ) -> Bool {
252
+ os_unfair_lock_trylock ( _lock)
253
+ }
254
+
182
255
}
183
256
}
184
257
0 commit comments