add coroutines
continuous-integration/drone/tag Build is passing Details

This commit is contained in:
Raffaele Mignone 2020-03-25 22:07:23 +01:00
parent d450f2096e
commit 48849063a4
Signed by: norangebit
GPG Key ID: F5255658CB220573
8 changed files with 32 additions and 90 deletions

View File

@ -1,12 +1,14 @@
package drills.drill03.exercise1
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.runBlocking
import util.active.toActive
import kotlin.time.ExperimentalTime
import kotlin.time.measureTime
@ExperimentalTime
fun main() {
val math = MathImpl().toActive(Math::class.java)
fun main() = runBlocking {
val (math, job) = MathImpl().toActive(Math::class.java)
val elapsed = measureTime {
for (i in 0 until 1000)
@ -14,4 +16,6 @@ fun main() {
}
println("Elapsed time: $elapsed")
job.cancelAndJoin()
}

View File

@ -1,7 +0,0 @@
package drills.drill03.exercise3
import java.io.Serializable
class AddTask(private val a: Int, private val b: Int) : Task {
override fun execute(): Serializable = a + b
}

View File

@ -1,26 +0,0 @@
package drills.drill03.exercise3
import util.rmi.Client
fun main() {
Client(clientHandler).start()
}
val clientHandler = {
val rev = Client.lookup("rev") as Rev
println("Enter two numbers:")
val a = readLine()?.toInt() ?: 0
val b = readLine()?.toInt() ?: 0
val sum = rev.executeTask(AddTask(a, b))
println("The sum of $a and $b is $sum")
println("Enter the number of which you want to calculate the factorial:")
val n = readLine()?.toInt() ?: 0
val fact = rev.executeTask(FactTask(n))
println("The factorial of $n is $fact")
}
fun fact(n: Int): Long = if (n <= 1) 1 else n * fact(n - 1)

View File

@ -1,9 +0,0 @@
package drills.drill03.exercise3
import java.io.Serializable
class FactTask(private val n: Int) : Task {
override fun execute(): Serializable = fact(n)
private fun fact(n: Int): Long = if (n <= 1) 1 else n * fact(n - 1)
}

View File

@ -1,15 +0,0 @@
package drills.drill03.exercise3
import java.io.Serializable
import java.rmi.Remote
import java.rmi.RemoteException
import java.rmi.server.UnicastRemoteObject
interface Rev : Remote {
@Throws(RemoteException::class)
fun executeTask(task: Task): Serializable
}
class RevImpl : Rev, UnicastRemoteObject() {
override fun executeTask(task: Task): Serializable = task.execute()
}

View File

@ -1,11 +0,0 @@
package drills.drill03.exercise3
import util.rmi.Server
fun main() {
Server {
System.setSecurityManager(SecurityManager())
val rev: Rev = RevImpl()
Server.bind(rev, "rev")
}.start()
}

View File

@ -1,7 +0,0 @@
package drills.drill03.exercise3
import java.io.Serializable
interface Task : Serializable {
fun execute(): Serializable
}

View File

@ -1,20 +1,18 @@
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>()
init {
Thread {
while (true)
queue.take().executeOn(target)
}.start()
}
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
if (method != null && args != null)
queue.add(Call(method, args))
@ -22,6 +20,15 @@ class ActiveObjectHandler(private val target: Any) : InvocationHandler {
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)
@ -29,10 +36,16 @@ class ActiveObjectHandler(private val target: Any) : InvocationHandler {
}
}
fun <T> Any.toActive(inter: Class<T>): T {
return Proxy.newProxyInstance(
this::class.java.classLoader,
arrayOf(inter),
ActiveObjectHandler(this)
) as T
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
)
}