add future implementation
This commit is contained in:
parent
48849063a4
commit
4782ec428f
@ -503,7 +503,7 @@ style:
|
|||||||
MagicNumber:
|
MagicNumber:
|
||||||
active: true
|
active: true
|
||||||
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
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
|
ignoreHashCodeFunction: true
|
||||||
ignorePropertyDeclaration: false
|
ignorePropertyDeclaration: false
|
||||||
ignoreLocalVariableDeclaration: 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