mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-11-29 21:48:45 +00:00
updates in coroutines
This commit is contained in:
parent
abd0cb2031
commit
0d8f844314
@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
## 0.4.19
|
## 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
|
## 0.4.18
|
||||||
|
|
||||||
* `Coroutines`:
|
* `Coroutines`:
|
||||||
|
@ -3,15 +3,15 @@ package dev.inmo.micro_utils.coroutines
|
|||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
|
|
||||||
suspend fun <T> Iterable<Deferred<T>>.awaitFirst(
|
suspend fun <T> Iterable<Deferred<T>>.awaitFirstWithDeferred(
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
cancelOnResult: Boolean = true
|
cancelOnResult: Boolean = true
|
||||||
): T = suspendCoroutine<T> { continuation ->
|
): Pair<Deferred<T>, T> = suspendCoroutine<Pair<Deferred<T>, T>> { continuation ->
|
||||||
scope.launch(SupervisorJob()) {
|
scope.launch(SupervisorJob()) {
|
||||||
val scope = this
|
val scope = this
|
||||||
forEach {
|
forEach {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
continuation.resume(it.await())
|
continuation.resume(it to it.await())
|
||||||
scope.cancel()
|
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(
|
suspend fun <T> Iterable<Deferred<T>>.awaitFirst(
|
||||||
cancelOthers: Boolean = true
|
cancelOthers: Boolean = true
|
||||||
): T = awaitFirst(CoroutineScope(coroutineContext), cancelOthers)
|
): 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