Skip to content

Instantly share code, notes, and snippets.

@Restioson
Created June 22, 2017 12:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Restioson/f6ab57fca89347154eda44232986ecd8 to your computer and use it in GitHub Desktop.
Save Restioson/f6ab57fca89347154eda44232986ecd8 to your computer and use it in GitHub Desktop.
/*
* This example is about using coroutines as state machines,
* in the same thread rather than as threads for asynchronous
* operations. It allows you to write sequential code such as
* code that waits for something to happen ONCE and then does
* something, essentially equivalent to adding an event
* listener which removes itself after it has run, but
* avoiding callback hell.
*/
package io.github.restioson.coroutinestuff
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.launch
import java.util.*
import java.util.concurrent.ConcurrentLinkedQueue
import kotlin.coroutines.experimental.Continuation
import kotlin.coroutines.experimental.suspendCoroutine
fun main(args: Array<String>) {
var lastUpdate = System.currentTimeMillis()
var delta: Long
var accumulator = 0L
launch(CommonPool) {
Batch.schedule {
println("This will run ahead of the other")
}
println("This will run before both")
Batch.run {
println("Hello from coro")
}
println("Done")
}
Batch.schedule {
println("You can also use schedule from non coroutine contexts!")
}
while (true) {
delta = System.currentTimeMillis() - lastUpdate
lastUpdate = System.currentTimeMillis()
accumulator += delta
if (accumulator >= 500) { // 1 tps
accumulator = 0
println("Updating")
Batch.execute()
println("Updated")
}
}
}
class BatchedFunc<R>(val func: () -> R, val coro: Continuation<R>?) {
operator fun invoke() {
val r = this.func.invoke()
this.coro?.resume(r)
}
}
object Batch {
private val batch: Queue<BatchedFunc<*>> = ConcurrentLinkedQueue()
fun <R> schedule(func: () -> R) = batch.add(BatchedFunc(func, null))
suspend fun <R> run(func: () -> R): R = suspendCoroutine {
batch.add(BatchedFunc(func, it))
}
internal fun execute() {
while (!batch.isEmpty()) {
batch.poll().invoke()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment