add future implementation
This commit is contained in:
parent
48849063a4
commit
4782ec428f
@ -503,7 +503,7 @@ style:
|
||||
MagicNumber:
|
||||
active: true
|
||||
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||
ignoreNumbers: '-1,0,1,2,100,500,1000'
|
||||
ignoreNumbers: '-1,0,1,2,3,42,100,500,1000,4242'
|
||||
ignoreHashCodeFunction: true
|
||||
ignorePropertyDeclaration: false
|
||||
ignoreLocalVariableDeclaration: false
|
||||
|
66
src/main/kotlin/util/future/Future.kt
Normal file
66
src/main/kotlin/util/future/Future.kt
Normal file
@ -0,0 +1,66 @@
|
||||
package util.future
|
||||
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
interface Future<T> {
|
||||
suspend fun get(): T
|
||||
suspend fun get(timeout: Long): T?
|
||||
fun isDone(): Boolean
|
||||
fun cancel()
|
||||
fun isCancelled(): Boolean
|
||||
}
|
||||
|
||||
class CoFuture<T>(private val func: suspend () -> T) : Future<T> {
|
||||
private var value: T? = null
|
||||
private var job = GlobalScope.launch {
|
||||
value = func()
|
||||
}
|
||||
|
||||
override suspend fun get(): T {
|
||||
job.join()
|
||||
return value!!
|
||||
}
|
||||
|
||||
override suspend fun get(timeout: Long): T? {
|
||||
delay(timeout)
|
||||
return value
|
||||
}
|
||||
|
||||
override fun isDone(): Boolean = job.isCompleted
|
||||
|
||||
override fun cancel() {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
override fun isCancelled(): Boolean = job.isCancelled
|
||||
}
|
||||
|
||||
fun <T> future(func: suspend () -> T): Future<T> = CoFuture(func)
|
||||
|
||||
fun <T> delayedEcho(value: T, delay: Long = 1000): Future<T> = future {
|
||||
delay(delay)
|
||||
value
|
||||
}
|
||||
|
||||
class MathFuture {
|
||||
fun add(a: Int, b: Int): Future<Int> = future { a + b }
|
||||
}
|
||||
|
||||
fun main() = runBlocking {
|
||||
val future = delayedEcho(42, delay = 2000)
|
||||
println("do other work.")
|
||||
println(future.get())
|
||||
|
||||
val math = MathFuture()
|
||||
val sums = (0 until 100)
|
||||
.map { math.add(it, it * 2) }
|
||||
|
||||
println("End all sums.")
|
||||
|
||||
sums.forEach {
|
||||
println(it.get())
|
||||
}
|
||||
}
|
45
src/main/kotlin/util/future/FutureHandler.kt
Normal file
45
src/main/kotlin/util/future/FutureHandler.kt
Normal file
@ -0,0 +1,45 @@
|
||||
package util.future
|
||||
|
||||
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 FutureHandler(private val target: Any) : InvocationHandler {
|
||||
private val queue = LinkedBlockingQueue<LatchFuture<*>>()
|
||||
|
||||
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
|
||||
val future = method!!.invoke(target, *args!!) as LatchFuture<*>
|
||||
queue.add(future)
|
||||
|
||||
return future
|
||||
}
|
||||
|
||||
fun start(): Job {
|
||||
return GlobalScope.launch {
|
||||
while (isActive || queue.isNotEmpty()) {
|
||||
queue.poll(100, TimeUnit.MILLISECONDS)
|
||||
?.exec()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> Any.toFutureHandler(inter: Class<T>): Pair<T, Job> {
|
||||
val futureHandler = FutureHandler(this)
|
||||
|
||||
val job = futureHandler.start()
|
||||
|
||||
return Pair(
|
||||
Proxy.newProxyInstance(
|
||||
this::class.java.classLoader,
|
||||
arrayOf(inter),
|
||||
futureHandler
|
||||
) as T, job
|
||||
)
|
||||
}
|
38
src/main/kotlin/util/future/LatchFuture.kt
Normal file
38
src/main/kotlin/util/future/LatchFuture.kt
Normal file
@ -0,0 +1,38 @@
|
||||
package util.future
|
||||
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.Future
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class LatchFuture<T>(private val func: () -> T) : Future<T> {
|
||||
private val latch = CountDownLatch(1)
|
||||
private var isCancelled = false
|
||||
private var value: T? = null
|
||||
|
||||
override fun isDone(): Boolean = value != null
|
||||
|
||||
override fun get(): T {
|
||||
latch.await()
|
||||
return value!!
|
||||
}
|
||||
|
||||
override fun get(p0: Long, p1: TimeUnit): T? {
|
||||
p1.sleep(p0)
|
||||
return value
|
||||
}
|
||||
|
||||
override fun cancel(p0: Boolean): Boolean {
|
||||
isCancelled = true
|
||||
latch.countDown()
|
||||
return isCancelled
|
||||
}
|
||||
|
||||
override fun isCancelled(): Boolean = isCancelled
|
||||
|
||||
fun exec() {
|
||||
if (!isCancelled) {
|
||||
value = func()
|
||||
latch.countDown()
|
||||
}
|
||||
}
|
||||
}
|
24
src/main/kotlin/util/future/Main.kt
Normal file
24
src/main/kotlin/util/future/Main.kt
Normal file
@ -0,0 +1,24 @@
|
||||
package util.future
|
||||
|
||||
import kotlinx.coroutines.cancelAndJoin
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.util.concurrent.Future
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.measureTime
|
||||
|
||||
@ExperimentalTime
|
||||
fun main() = runBlocking {
|
||||
val (math, job) = FutureMathImpl().toFutureHandler(FutureMath::class.java)
|
||||
|
||||
lateinit var sums: List<Future<Int>>
|
||||
|
||||
val elapsed = measureTime {
|
||||
sums = (0 until 100).map { math.add(it, it * 2) }
|
||||
}
|
||||
|
||||
println("Elapsed time: $elapsed")
|
||||
|
||||
sums.forEach { println(it.get()) }
|
||||
|
||||
job.cancelAndJoin()
|
||||
}
|
13
src/main/kotlin/util/future/Math.kt
Normal file
13
src/main/kotlin/util/future/Math.kt
Normal file
@ -0,0 +1,13 @@
|
||||
package util.future
|
||||
|
||||
import java.util.concurrent.Future
|
||||
|
||||
interface FutureMath {
|
||||
fun add(a: Int, b: Int): Future<Int>
|
||||
}
|
||||
|
||||
class FutureMathImpl : FutureMath {
|
||||
override fun add(a: Int, b: Int): Future<Int> {
|
||||
return LatchFuture { a + b }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user