Skip to content

Instantly share code, notes, and snippets.

@elizarov
Last active April 28, 2021 12:42
Show Gist options
  • Save elizarov/d6da6bdcae6a1726d11e14add140069d to your computer and use it in GitHub Desktop.
Save elizarov/d6da6bdcae6a1726d11e14add140069d to your computer and use it in GitHub Desktop.
Using Kotlin Coroutine context to keep a mutable counter
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import java.util.concurrent.atomic.AtomicInteger
import kotlin.coroutines.experimental.AbstractCoroutineContextElement
import kotlin.coroutines.experimental.CoroutineContext
import kotlin.coroutines.experimental.intrinsics.*
// coroutine context element that keeps a (mutable) integer counter
class Counter : AbstractCoroutineContextElement(Key) {
companion object Key : CoroutineContext.Key<Counter>
private val current = AtomicInteger()
public val value: Int get() = current.get()
public fun inc() = current.incrementAndGet()
}
// suspending function that increments a counter in the context
// note: it does not actually suspend execution
suspend fun incCounter(): Int = suspendCoroutineOrReturn { cont ->
cont.context[Counter]!!.inc()
}
// test code
fun main(args: Array<String>) = runBlocking {
val counter = Counter() // create a counter
val ctx = CommonPool + counter // create combined context with counter and CommonPool dispatcher
// launch a job in this combined context that does a few increments
val job = launch(ctx) {
incCounter()
incCounter()
incCounter()
}
// wait for a coroutine job to complete
job.join()
// print counter value
println("Counter value = ${counter.value}")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment