blob: 62a71e02f15d1ed4685b04461a23f159a3dad956 (
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
internal typealias Handle = Long
internal class ConcurrentHandleMap<T>(
private val leftMap: MutableMap<Handle, T> = mutableMapOf(),
private val rightMap: MutableMap<T, Handle> = mutableMapOf()
) {
private val lock = java.util.concurrent.locks.ReentrantLock()
private val currentHandle = AtomicLong(0L)
private val stride = 1L
fun insert(obj: T): Handle =
lock.withLock {
rightMap[obj] ?:
currentHandle.getAndAdd(stride)
.also { handle ->
leftMap[handle] = obj
rightMap[obj] = handle
}
}
fun get(handle: Handle) = lock.withLock {
leftMap[handle]
}
fun delete(handle: Handle) {
this.remove(handle)
}
fun remove(handle: Handle): T? =
lock.withLock {
leftMap.remove(handle)?.let { obj ->
rightMap.remove(obj)
obj
}
}
}
interface ForeignCallback : com.sun.jna.Callback {
public fun callback(handle: Handle, method: Int, argsData: Pointer, argsLen: Int, outBuf: RustBufferByReference): Int
}
// 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.
internal const val IDX_CALLBACK_FREE = 0
// Callback return codes
internal const val UNIFFI_CALLBACK_SUCCESS = 0
internal const val UNIFFI_CALLBACK_ERROR = 1
internal const val UNIFFI_CALLBACK_UNEXPECTED_ERROR = 2
public abstract class FfiConverterCallbackInterface<CallbackInterface>(
protected val foreignCallback: ForeignCallback
): FfiConverter<CallbackInterface, Handle> {
private val handleMap = ConcurrentHandleMap<CallbackInterface>()
// Registers the foreign callback with the Rust side.
// This method is generated for each callback interface.
internal abstract fun register(lib: _UniFFILib)
fun drop(handle: Handle): RustBuffer.ByValue {
return handleMap.remove(handle).let { RustBuffer.ByValue() }
}
override fun lift(value: Handle): CallbackInterface {
return handleMap.get(value) ?: throw InternalException("No callback in handlemap; this is a Uniffi bug")
}
override fun read(buf: ByteBuffer) = lift(buf.getLong())
override fun lower(value: CallbackInterface) =
handleMap.insert(value).also {
assert(handleMap.get(it) === value) { "Handle map is not returning the object we just placed there. This is a bug in the HandleMap." }
}
override fun allocationSize(value: CallbackInterface) = 8
override fun write(value: CallbackInterface, buf: ByteBuffer) {
buf.putLong(lower(value))
}
}
|