From 60dea2a5181a272492b8e105d8231ac195ee4f74 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 5 Feb 2021 15:38:20 +0600 Subject: [PATCH] DoWithFirstBuilder --- CHANGELOG.md | 4 ++ .../micro_utils/coroutines/DoWithFirst.kt | 43 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c093b531157..4ca7ccbf0df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## 0.4.24 +* `Coroutines`: + * New class `DoWithFirstBuilder` + * Several new extensions like `firstOf`/`first`/`invokeOnFirstOf` + ## 0.4.23 * `Versions`: diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/DoWithFirst.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/DoWithFirst.kt index 8bc71da51cb..91f6bfd8c1b 100644 --- a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/DoWithFirst.kt +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/DoWithFirst.kt @@ -9,6 +9,17 @@ class DeferredAction( suspend operator fun invoke() = callback(deferred.await()) } +class DoWithFirstBuilder( + private val scope: CoroutineScope +) { + private val deferreds = mutableListOf>() + operator fun plus(block: suspend CoroutineScope.() -> T) { + deferreds.add(scope.async(start = CoroutineStart.LAZY, block = block)) + } + + fun build() = deferreds.toList() +} + fun Deferred.buildAction(callback: suspend (T) -> O) = DeferredAction(this, callback) suspend fun Iterable>.invokeFirstOf( @@ -32,9 +43,41 @@ suspend fun Iterable>.invokeOnFirst( callback: suspend (T) -> O ): O = map { it.buildAction(callback) }.invokeFirstOf(scope, cancelOnResult) +suspend fun CoroutineScope.invokeOnFirstOf( + cancelOnResult: Boolean = true, + block: DoWithFirstBuilder.() -> Unit, + callback: suspend (T) -> O +) = firstOf( + DoWithFirstBuilder(this).apply(block).build(), + cancelOnResult +).let { callback(it) } + suspend fun invokeOnFirst( scope: CoroutineScope, vararg variants: Deferred, cancelOnResult: Boolean = true, callback: suspend (T) -> O ): O = variants.toList().invokeOnFirst(scope, cancelOnResult, callback) + +suspend fun CoroutineScope.firstOf( + variants: Iterable>, + cancelOnResult: Boolean = true +) = variants.invokeOnFirst(this, cancelOnResult) { it } + +suspend fun CoroutineScope.firstOf( + cancelOnResult: Boolean = true, + block: DoWithFirstBuilder.() -> Unit +) = firstOf( + DoWithFirstBuilder(this).apply(block).build(), + cancelOnResult +) + +suspend fun CoroutineScope.firstOf( + vararg variants: Deferred, + cancelOnResult: Boolean = true +) = firstOf(variants.toList(), cancelOnResult) + +suspend fun List>.first( + scope: CoroutineScope, + cancelOnResult: Boolean = true +) = scope.firstOf(this, cancelOnResult)