DoWithFirstBuilder

This commit is contained in:
InsanusMokrassar 2021-02-05 15:38:20 +06:00
parent 3877f49278
commit 60dea2a518
2 changed files with 47 additions and 0 deletions

View File

@ -2,6 +2,10 @@
## 0.4.24
* `Coroutines`:
* New class `DoWithFirstBuilder`
* Several new extensions like `firstOf`/`first`/`invokeOnFirstOf`
## 0.4.23
* `Versions`:

View File

@ -9,6 +9,17 @@ class DeferredAction<T, O>(
suspend operator fun invoke() = callback(deferred.await())
}
class DoWithFirstBuilder<T>(
private val scope: CoroutineScope
) {
private val deferreds = mutableListOf<Deferred<T>>()
operator fun plus(block: suspend CoroutineScope.() -> T) {
deferreds.add(scope.async(start = CoroutineStart.LAZY, block = block))
}
fun build() = deferreds.toList()
}
fun <T, O> Deferred<T>.buildAction(callback: suspend (T) -> O) = DeferredAction(this, callback)
suspend fun <O> Iterable<DeferredAction<*, O>>.invokeFirstOf(
@ -32,9 +43,41 @@ suspend fun <T, O> Iterable<Deferred<T>>.invokeOnFirst(
callback: suspend (T) -> O
): O = map { it.buildAction(callback) }.invokeFirstOf(scope, cancelOnResult)
suspend fun <T, O> CoroutineScope.invokeOnFirstOf(
cancelOnResult: Boolean = true,
block: DoWithFirstBuilder<T>.() -> Unit,
callback: suspend (T) -> O
) = firstOf(
DoWithFirstBuilder<T>(this).apply(block).build(),
cancelOnResult
).let { callback(it) }
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)
suspend fun <T> CoroutineScope.firstOf(
variants: Iterable<Deferred<T>>,
cancelOnResult: Boolean = true
) = variants.invokeOnFirst(this, cancelOnResult) { it }
suspend fun <T> CoroutineScope.firstOf(
cancelOnResult: Boolean = true,
block: DoWithFirstBuilder<T>.() -> Unit
) = firstOf(
DoWithFirstBuilder<T>(this).apply(block).build(),
cancelOnResult
)
suspend fun <T> CoroutineScope.firstOf(
vararg variants: Deferred<T>,
cancelOnResult: Boolean = true
) = firstOf(variants.toList(), cancelOnResult)
suspend fun <T> List<Deferred<T>>.first(
scope: CoroutineScope,
cancelOnResult: Boolean = true
) = scope.firstOf(this, cancelOnResult)