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 package drills.drill03.exercise1
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.runBlocking
import util.active.toActive import util.active.toActive
import kotlin.time.ExperimentalTime import kotlin.time.ExperimentalTime
import kotlin.time.measureTime import kotlin.time.measureTime
@ExperimentalTime @ExperimentalTime
fun main() { fun main() = runBlocking {
val math = MathImpl().toActive(Math::class.java) val (math, job) = MathImpl().toActive(Math::class.java)
val elapsed = measureTime { val elapsed = measureTime {
for (i in 0 until 1000) for (i in 0 until 1000)
@ -14,4 +16,6 @@ fun main() {
} }
println("Elapsed time: $elapsed") 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 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.InvocationHandler
import java.lang.reflect.Method import java.lang.reflect.Method
import java.lang.reflect.Proxy import java.lang.reflect.Proxy
import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.TimeUnit
class ActiveObjectHandler(private val target: Any) : InvocationHandler { class ActiveObjectHandler(private val target: Any) : InvocationHandler {
private val queue = LinkedBlockingQueue<Call>() 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 { override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
if (method != null && args != null) if (method != null && args != null)
queue.add(Call(method, args)) queue.add(Call(method, args))
@ -22,6 +20,15 @@ class ActiveObjectHandler(private val target: Any) : InvocationHandler {
return Unit 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>) { data class Call(val method: Method, val args: Array<out Any>) {
fun executeOn(target: Any) { fun executeOn(target: Any) {
method.invoke(target, *args) method.invoke(target, *args)
@ -29,10 +36,16 @@ class ActiveObjectHandler(private val target: Any) : InvocationHandler {
} }
} }
fun <T> Any.toActive(inter: Class<T>): T { fun <T> Any.toActive(inter: Class<T>): Pair<T, Job> {
return Proxy.newProxyInstance( val active = ActiveObjectHandler(this)
this::class.java.classLoader,
arrayOf(inter), val job = active.start()
ActiveObjectHandler(this)
) as T return Pair(
Proxy.newProxyInstance(
this::class.java.classLoader,
arrayOf(inter),
active
) as T, job
)
} }