mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-12-22 16:47:15 +00:00
updates in coroutines
This commit is contained in:
parent
abd0cb2031
commit
0d8f844314
@ -2,6 +2,12 @@
|
||||
|
||||
## 0.4.19
|
||||
|
||||
* `Coroutines`:
|
||||
* New extension `Iterable<Deferred>#awaitFirstWithDeferred` has been added to identify which of `Deferred`s was
|
||||
normally completed
|
||||
* New extensions `Iterable<Deferred<T>>#invokeOnFirst` and `Iterable<DeferredAction<*, O>>.invokeFirstOf` have been
|
||||
added
|
||||
|
||||
## 0.4.18
|
||||
|
||||
* `Coroutines`:
|
||||
|
@ -3,15 +3,15 @@ package dev.inmo.micro_utils.coroutines
|
||||
import kotlinx.coroutines.*
|
||||
import kotlin.coroutines.*
|
||||
|
||||
suspend fun <T> Iterable<Deferred<T>>.awaitFirst(
|
||||
suspend fun <T> Iterable<Deferred<T>>.awaitFirstWithDeferred(
|
||||
scope: CoroutineScope,
|
||||
cancelOnResult: Boolean = true
|
||||
): T = suspendCoroutine<T> { continuation ->
|
||||
): Pair<Deferred<T>, T> = suspendCoroutine<Pair<Deferred<T>, T>> { continuation ->
|
||||
scope.launch(SupervisorJob()) {
|
||||
val scope = this
|
||||
forEach {
|
||||
scope.launch {
|
||||
continuation.resume(it.await())
|
||||
continuation.resume(it to it.await())
|
||||
scope.cancel()
|
||||
}
|
||||
}
|
||||
@ -27,6 +27,11 @@ suspend fun <T> Iterable<Deferred<T>>.awaitFirst(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun <T> Iterable<Deferred<T>>.awaitFirst(
|
||||
scope: CoroutineScope,
|
||||
cancelOnResult: Boolean = true
|
||||
): T = awaitFirstWithDeferred(scope, cancelOnResult).second
|
||||
suspend fun <T> Iterable<Deferred<T>>.awaitFirst(
|
||||
cancelOthers: Boolean = true
|
||||
): T = awaitFirst(CoroutineScope(coroutineContext), cancelOthers)
|
||||
|
@ -0,0 +1,40 @@
|
||||
package dev.inmo.micro_utils.coroutines
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
class DeferredAction<T, O>(
|
||||
val deferred: Deferred<T>,
|
||||
val callback: suspend (T) -> O
|
||||
) {
|
||||
suspend operator fun invoke() = callback(deferred.await())
|
||||
}
|
||||
|
||||
fun <T, O> Deferred<T>.buildAction(callback: suspend (T) -> O) = DeferredAction(this, callback)
|
||||
|
||||
suspend fun <O> Iterable<DeferredAction<*, O>>.invokeFirstOf(
|
||||
scope: CoroutineScope,
|
||||
cancelOnResult: Boolean = true
|
||||
): O {
|
||||
return map { it.deferred }.awaitFirstWithDeferred(scope, cancelOnResult).let { result ->
|
||||
first { it.deferred == result.first }.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun <O> invokeFirstOf(
|
||||
scope: CoroutineScope,
|
||||
vararg variants: DeferredAction<*, O>,
|
||||
cancelOnResult: Boolean = true
|
||||
): O = variants.toList().invokeFirstOf(scope, cancelOnResult)
|
||||
|
||||
suspend fun <T, O> Iterable<Deferred<T>>.invokeOnFirst(
|
||||
scope: CoroutineScope,
|
||||
cancelOnResult: Boolean = true,
|
||||
callback: suspend (T) -> O
|
||||
): O = map { it.buildAction(callback) }.invokeFirstOf(scope, cancelOnResult)
|
||||
|
||||
suspend fun <T, O> invokeOnFirst(
|
||||
scope: CoroutineScope,
|
||||
vararg variants: Deferred<T>,
|
||||
cancelOnResult: Boolean = true,
|
||||
callback: suspend (T) -> O
|
||||
): O = variants.toList().invokeOnFirst(scope, cancelOnResult, callback)
|
@ -0,0 +1,27 @@
|
||||
package dev.inmo.micro_utils.coroutines
|
||||
|
||||
import dev.inmo.micro_utils.coroutines.asDeferred
|
||||
import dev.inmo.micro_utils.coroutines.launchSynchronously
|
||||
import kotlinx.coroutines.*
|
||||
import kotlin.test.*
|
||||
|
||||
class DoWithFirstTests {
|
||||
@Test
|
||||
fun testHandleOneOf() {
|
||||
val scope = CoroutineScope(Dispatchers.Default)
|
||||
val happenedDeferreds = mutableListOf<Int>()
|
||||
val deferredWhichMustHappen = (-1).asDeferred
|
||||
scope.launchSynchronously {
|
||||
scope.launch {
|
||||
((0 until 100).map {
|
||||
DeferredAction(
|
||||
scope.async { delay(10000); it },
|
||||
happenedDeferreds::add
|
||||
)
|
||||
} + DeferredAction(deferredWhichMustHappen, happenedDeferreds::add)).invokeFirstOf(scope)
|
||||
}.join()
|
||||
}
|
||||
assertEquals(1, happenedDeferreds.size)
|
||||
assertEquals(scope.launchSynchronously { deferredWhichMustHappen.await() }, happenedDeferreds.first())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user