Last active
April 28, 2021 12:42
-
-
Save elizarov/d6da6bdcae6a1726d11e14add140069d to your computer and use it in GitHub Desktop.
Using Kotlin Coroutine context to keep a mutable counter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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