Skip to content

Instantly share code, notes, and snippets.

@octylFractal
Created March 3, 2020 19:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save octylFractal/fd86b67bbdbf61f02c853142aced0534 to your computer and use it in GitHub Desktop.
Save octylFractal/fd86b67bbdbf61f02c853142aced0534 to your computer and use it in GitHub Desktop.
package kotlin_playground
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
suspend fun main() {
val latch = CountDownLatch(50)
coroutineScope {
val initial = launch {
printStamped("Initial await")
latch.await()
printStamped("Initial await released!")
}
for (i in 1..50) {
launch {
printStamped("Count down $i")
latch.countDown()
}
}
initial.join()
printStamped("After await")
latch.await()
printStamped("After await released!")
}
}
private fun printStamped(any: Any) {
println("${System.currentTimeMillis()}: $any")
}
class CountDownLatch(
initialCount: Int
) {
private var count = initialCount
private val mutex = Mutex()
private val awaiters = mutableSetOf<Continuation<Unit>>()
suspend fun countDown() {
if (count == 0) {
return
}
mutex.withLock {
if (count == 0) {
return
}
count--
if (count == 0) {
releaseAll()
}
}
}
private fun releaseAll() {
for (awaiter in awaiters) {
awaiter.resume(Unit)
}
}
suspend fun await() {
if (count == 0) {
return
}
mutex.withLock {
if (count == 0) {
return
}
}
suspendCancellableCoroutine<Unit> {
awaiters.add(it)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment