awaitFirst

This commit is contained in:
InsanusMokrassar 2021-01-17 17:15:54 +06:00
parent 9acb9af338
commit a3087cb650
3 changed files with 68 additions and 0 deletions

View File

@ -2,6 +2,8 @@
## 0.4.18 ## 0.4.18
* `Coroutines`:
* New extension `Iterable<Deferred>#awaitFirst` has been added
* `Serialization` * `Serialization`
* `Base 64` * `Base 64`
* New `Base64ByteArraySerializer` has been added * New `Base64ByteArraySerializer` has been added

View File

@ -0,0 +1,32 @@
package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.*
import kotlin.coroutines.*
suspend fun <T> Iterable<Deferred<T>>.awaitFirst(
scope: CoroutineScope,
cancelOnResult: Boolean = true
): T = suspendCoroutine<T> { continuation ->
scope.launch(SupervisorJob()) {
val scope = this
forEach {
scope.launch {
continuation.resume(it.await())
scope.cancel()
}
}
}
}.also {
if (cancelOnResult) {
forEach {
try {
it.cancel()
} catch (e: IllegalStateException) {
e.printStackTrace()
}
}
}
}
suspend fun <T> Iterable<Deferred<T>>.awaitFirst(
cancelOthers: Boolean = true
): T = awaitFirst(CoroutineScope(coroutineContext), cancelOthers)

View File

@ -0,0 +1,34 @@
package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.*
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class AwaitFirstTests {
private fun CoroutineScope.createTestDeferred(value: Int, wait: Long = 100000) = async(start = CoroutineStart.LAZY) { delay(wait); value }
@Test
fun testThatAwaitFirstIsWorkingCorrectly() {
val baseScope = CoroutineScope(Dispatchers.Default)
val resultDeferred = baseScope.createTestDeferred(-1, 0)
val deferreds = listOf(
baseScope.async { createTestDeferred(0) },
baseScope.async { createTestDeferred(1) },
baseScope.async { createTestDeferred(2) },
resultDeferred
)
val controlJob = baseScope.launch {
delay(1000000)
}
val result = baseScope.launchSynchronously {
val result = deferreds.awaitFirst(baseScope)
assertTrue(baseScope.isActive)
assertTrue(controlJob.isActive)
result
}
assertEquals(baseScope.launchSynchronously { resultDeferred.await() }, result)
assertTrue(deferreds.all { it == resultDeferred || it.isCancelled })
}
}