Skip to content

Commit e308cac

Browse files
committed
Introduced LockIsolated into the codebase
1 parent df3e2fc commit e308cac

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

Sources/InterposeKit/Hooks/HookStrategy/ObjectHookStrategy/ObjectSubclassManager.swift

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ internal enum ObjectSubclassManager {
136136
) -> String {
137137
let className = NSStringFromClass(perceivedClass)
138138

139-
let counterSuffix: String = self.subclassCounterQueue.sync {
140-
self.subclassCounter &+= 1
141-
return String(format: "%04llx", self.subclassCounter)
139+
let counterSuffix: String = self.subclassCounter.withValue { counter in
140+
counter &+= 1
141+
return String(format: "%04llx", counter)
142142
}
143143

144144
return "\(self.namePrefix)_\(className)_\(counterSuffix)"
@@ -147,10 +147,7 @@ internal enum ObjectSubclassManager {
147147
/// The prefix used for all dynamically created subclass names.
148148
private static let namePrefix = "InterposeKit"
149149

150-
/// A global counter for generating unique subclass name suffixes.
151-
private static var subclassCounter: UInt64 = 0
152-
153-
/// A serial queue to ensure thread-safe access to `subclassCounter`.
154-
private static let subclassCounterQueue = DispatchQueue(label: "com.steipete.InterposeKit.subclassCounter")
150+
/// A lock-isolated global counter for generating unique subclass name suffixes.
151+
private static let subclassCounter = LockIsolated<UInt64>(0)
155152

156153
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// A modified version from Point-Free’s Concurrency Extras package:
2+
// https://github.com/pointfreeco/swift-concurrency-extras
3+
//
4+
// Copyright (c) 2023 Point-Free
5+
// Licensed under the MIT license.
6+
7+
import Foundation
8+
9+
internal final class LockIsolated<Value>: @unchecked Sendable {
10+
private var _value: Value
11+
private let lock = NSRecursiveLock()
12+
13+
internal init(_ value: @autoclosure @Sendable () throws -> Value) rethrows {
14+
self._value = try value()
15+
}
16+
17+
internal var value: Value {
18+
self.lock.sync {
19+
self._value
20+
}
21+
}
22+
23+
internal func withValue<T: Sendable>(
24+
_ operation: @Sendable (inout Value) throws -> T
25+
) rethrows -> T {
26+
try self.lock.sync {
27+
var value = self._value
28+
defer { self._value = value }
29+
return try operation(&value)
30+
}
31+
}
32+
}
33+
34+
extension NSRecursiveLock {
35+
@discardableResult
36+
fileprivate func sync<R>(work: () throws -> R) rethrows -> R {
37+
self.lock()
38+
defer { self.unlock() }
39+
return try work()
40+
}
41+
}

0 commit comments

Comments
 (0)