blob: 9ae62d1667e983efd4a2a886a813ad93eda039a5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
fileprivate extension NSLock {
func withLock<T>(f: () throws -> T) rethrows -> T {
self.lock()
defer { self.unlock() }
return try f()
}
}
fileprivate typealias UniFFICallbackHandle = UInt64
fileprivate class UniFFICallbackHandleMap<T> {
private var leftMap: [UniFFICallbackHandle: T] = [:]
private var counter: [UniFFICallbackHandle: UInt64] = [:]
private var rightMap: [ObjectIdentifier: UniFFICallbackHandle] = [:]
private let lock = NSLock()
private var currentHandle: UniFFICallbackHandle = 0
private let stride: UniFFICallbackHandle = 1
func insert(obj: T) -> UniFFICallbackHandle {
lock.withLock {
let id = ObjectIdentifier(obj as AnyObject)
let handle = rightMap[id] ?? {
currentHandle += stride
let handle = currentHandle
leftMap[handle] = obj
rightMap[id] = handle
return handle
}()
counter[handle] = (counter[handle] ?? 0) + 1
return handle
}
}
func get(handle: UniFFICallbackHandle) -> T? {
lock.withLock {
leftMap[handle]
}
}
func delete(handle: UniFFICallbackHandle) {
remove(handle: handle)
}
@discardableResult
func remove(handle: UniFFICallbackHandle) -> T? {
lock.withLock {
defer { counter[handle] = (counter[handle] ?? 1) - 1 }
guard counter[handle] == 1 else { return leftMap[handle] }
let obj = leftMap.removeValue(forKey: handle)
if let obj = obj {
rightMap.removeValue(forKey: ObjectIdentifier(obj as AnyObject))
}
return obj
}
}
}
// Magic number for the Rust proxy to call using the same mechanism as every other method,
// to free the callback once it's dropped by Rust.
private let IDX_CALLBACK_FREE: Int32 = 0
// Callback return codes
private let UNIFFI_CALLBACK_SUCCESS: Int32 = 0
private let UNIFFI_CALLBACK_ERROR: Int32 = 1
private let UNIFFI_CALLBACK_UNEXPECTED_ERROR: Int32 = 2
|