File tree 2 files changed +43
-0
lines changed
2 files changed +43
-0
lines changed Original file line number Diff line number Diff line change @@ -22,6 +22,19 @@ public protocol NSLocking {
22
22
func unlock( )
23
23
}
24
24
25
+ extension NSLocking {
26
+ @_alwaysEmitIntoClient
27
+ @_disfavoredOverload
28
+ public func withLock< R> ( _ body: ( ) throws -> R ) rethrows -> R {
29
+ self . lock ( )
30
+ defer {
31
+ self . unlock ( )
32
+ }
33
+
34
+ return try body ( )
35
+ }
36
+ }
37
+
25
38
#if os(Windows)
26
39
private typealias _MutexPointer = UnsafeMutablePointer < SRWLOCK >
27
40
private typealias _RecursiveMutexPointer = UnsafeMutablePointer < CRITICAL_SECTION >
Original file line number Diff line number Diff line change @@ -14,6 +14,7 @@ class TestNSLock: XCTestCase {
14
14
( " test_lockWait " , test_lockWait) ,
15
15
( " test_threadsAndLocks " , test_threadsAndLocks) ,
16
16
( " test_recursiveLock " , test_recursiveLock) ,
17
+ ( " test_withLock " , test_withLock) ,
17
18
18
19
]
19
20
}
@@ -187,4 +188,33 @@ class TestNSLock: XCTestCase {
187
188
188
189
threadCompletedCondition. unlock ( )
189
190
}
191
+
192
+ func test_withLock( ) {
193
+ let lock = NSLock ( )
194
+
195
+ var counter = 0
196
+ let counterIncrementPerThread = 10_000
197
+
198
+ let threadCount = 10
199
+
200
+ let threadCompletedExpectation = expectation ( description: " Expected threads to complete. " )
201
+ threadCompletedExpectation. expectedFulfillmentCount = threadCount
202
+
203
+ for _ in 0 ..< threadCount {
204
+ let thread = Thread {
205
+ for _ in 0 ..< counterIncrementPerThread {
206
+ lock. withLock {
207
+ counter += 1
208
+ }
209
+ }
210
+
211
+ threadCompletedExpectation. fulfill ( )
212
+ }
213
+ thread. start ( )
214
+ }
215
+
216
+ wait ( for: [ threadCompletedExpectation] , timeout: 10 )
217
+
218
+ XCTAssertEqual ( counter, counterIncrementPerThread * threadCount)
219
+ }
190
220
}
You can’t perform that action at this time.
0 commit comments