52 lines
1.3 KiB
Kotlin
52 lines
1.3 KiB
Kotlin
package util.active
|
|
|
|
import kotlinx.coroutines.GlobalScope
|
|
import kotlinx.coroutines.Job
|
|
import kotlinx.coroutines.isActive
|
|
import kotlinx.coroutines.launch
|
|
import java.lang.reflect.InvocationHandler
|
|
import java.lang.reflect.Method
|
|
import java.lang.reflect.Proxy
|
|
import java.util.concurrent.LinkedBlockingQueue
|
|
import java.util.concurrent.TimeUnit
|
|
|
|
class ActiveObjectHandler(private val target: Any) : InvocationHandler {
|
|
private val queue = LinkedBlockingQueue<Call>()
|
|
|
|
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
|
|
if (method != null && args != null)
|
|
queue.add(Call(method, args))
|
|
|
|
return Unit
|
|
}
|
|
|
|
fun start(): Job {
|
|
return GlobalScope.launch {
|
|
while (isActive || queue.isNotEmpty()) {
|
|
queue.poll(100, TimeUnit.MILLISECONDS)
|
|
?.executeOn(target) ?: continue
|
|
}
|
|
}
|
|
}
|
|
|
|
data class Call(val method: Method, val args: Array<out Any>) {
|
|
fun executeOn(target: Any) {
|
|
method.invoke(target, *args)
|
|
}
|
|
}
|
|
}
|
|
|
|
fun <T> Any.toActive(inter: Class<T>): Pair<T, Job> {
|
|
val active = ActiveObjectHandler(this)
|
|
|
|
val job = active.start()
|
|
|
|
return Pair(
|
|
Proxy.newProxyInstance(
|
|
this::class.java.classLoader,
|
|
arrayOf(inter),
|
|
active
|
|
) as T, job
|
|
)
|
|
}
|