1+ #if canImport(Darwin)
2+ import Darwin
3+ #endif
14import Foundation
25import SourceKittenFramework
36import SwiftParser
@@ -66,19 +69,19 @@ private var assertHandlers = [FileCacheKey: AssertHandler]()
6669private var assertHandlerCache = Cache ( { file in assertHandlers [ file. cacheKey] } )
6770
6871private struct RebuildQueue {
69- private let lock = NSLock ( )
72+ private let lock = PlatformLock ( )
7073 private var queue = [ Structure] ( )
7174
7275 mutating func append( _ structure: Structure ) {
73- lock. lock ( )
74- defer { lock . unlock ( ) }
75- queue . append ( structure )
76+ lock. doLocked {
77+ queue . append ( structure )
78+ }
7679 }
7780
7881 mutating func clear( ) {
79- lock. lock ( )
80- defer { lock . unlock ( ) }
81- queue . removeAll ( keepingCapacity : false )
82+ lock. doLocked {
83+ queue . removeAll ( keepingCapacity : false )
84+ }
8285 }
8386}
8487
@@ -87,44 +90,38 @@ private var queueForRebuild = RebuildQueue()
8790private class Cache < T> {
8891 private var values = [ FileCacheKey: T] ( )
8992 private let factory : ( SwiftLintFile ) -> T
90- private let lock = NSLock ( )
93+ private let lock = PlatformLock ( )
9194
9295 fileprivate init ( _ factory: @escaping ( SwiftLintFile ) -> T ) {
9396 self . factory = factory
9497 }
9598
9699 fileprivate func get( _ file: SwiftLintFile ) -> T {
97100 let key = file. cacheKey
98- lock. lock ( )
99- defer { lock. unlock ( ) }
100- if let cachedValue = values [ key] {
101- return cachedValue
101+ return lock. doLocked {
102+ if let cachedValue = values [ key] {
103+ return cachedValue
104+ }
105+ let value = factory ( file)
106+ values [ key] = value
107+ return value
102108 }
103- let value = factory ( file)
104- values [ key] = value
105- return value
106109 }
107110
108111 fileprivate func invalidate( _ file: SwiftLintFile ) {
109- doLocked { values. removeValue ( forKey: file. cacheKey) }
112+ lock . doLocked { values. removeValue ( forKey: file. cacheKey) }
110113 }
111114
112115 fileprivate func clear( ) {
113- doLocked { values. removeAll ( keepingCapacity: false ) }
116+ lock . doLocked { values. removeAll ( keepingCapacity: false ) }
114117 }
115118
116119 fileprivate func set( key: FileCacheKey , value: T ) {
117- doLocked { values [ key] = value }
120+ lock . doLocked { values [ key] = value }
118121 }
119122
120123 fileprivate func unset( key: FileCacheKey ) {
121- doLocked { values. removeValue ( forKey: key) }
122- }
123-
124- private func doLocked( block: ( ) -> Void ) {
125- lock. lock ( )
126- block ( )
127- lock. unlock ( )
124+ lock. doLocked { values. removeValue ( forKey: key) }
128125 }
129126}
130127
@@ -266,3 +263,31 @@ extension SwiftLintFile {
266263 commandsCache. clear ( )
267264 }
268265}
266+
267+ private final class PlatformLock {
268+ #if canImport(Darwin)
269+ private let primitiveLock : UnsafeMutablePointer < os_unfair_lock >
270+ #else
271+ private let primitiveLock = NSLock ( )
272+ #endif
273+
274+ init ( ) {
275+ #if canImport(Darwin)
276+ primitiveLock = UnsafeMutablePointer< os_unfair_lock> . allocate( capacity: 1 )
277+ primitiveLock. initialize ( to: os_unfair_lock ( ) )
278+ #endif
279+ }
280+
281+ @discardableResult
282+ func doLocked< U> ( _ closure: ( ) -> U ) -> U {
283+ #if canImport(Darwin)
284+ os_unfair_lock_lock ( primitiveLock)
285+ defer { os_unfair_lock_unlock ( primitiveLock) }
286+ return closure ( )
287+ #else
288+ primitiveLock. lock ( )
289+ defer { primitiveLock. unlock ( ) }
290+ return closure ( )
291+ #endif
292+ }
293+ }
0 commit comments