From 36deab490998b3c8e125b79facb46420710f5b3f Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 5 Apr 2021 16:10:36 +0600 Subject: [PATCH] weak jobs workaround --- CHANGELOG.md | 4 ++ .../inmo/micro_utils/coroutines/WeakJob.kt | 31 ++++++++++++++ .../inmo/micro_utils/coroutines/WeakJob.kt | 40 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/WeakJob.kt create mode 100644 coroutines/src/jvmTest/kotlin/dev/inmo/micro_utils/coroutines/WeakJob.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 57848da8fc0..3ccdc09591a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## 0.4.33 +* `Coroutines` + * Add `WeakJob` workaround: + * `CoroutineScope#` + ## 0.4.32 * `Versions`: diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/WeakJob.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/WeakJob.kt new file mode 100644 index 00000000000..a11dc6b99ed --- /dev/null +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/WeakJob.kt @@ -0,0 +1,31 @@ +package dev.inmo.micro_utils.coroutines + +import kotlinx.coroutines.* +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext + +fun CoroutineScope.createWeakSubScope() = CoroutineScope(coroutineContext.minusKey(Job)).also { newScope -> + coroutineContext.job.invokeOnCompletion { newScope.cancel() } +} + +fun CoroutineScope.weakLaunch( + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, + block: suspend CoroutineScope.() -> Unit +): Job { + val scope = createWeakSubScope() + val job = scope.launch(context, start, block) + job.invokeOnCompletion { scope.cancel() } + return job +} + +fun CoroutineScope.weakAsync( + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, + block: suspend CoroutineScope.() -> T +): Deferred { + val scope = createWeakSubScope() + val deferred = scope.async(context, start, block) + deferred.invokeOnCompletion { scope.cancel() } + return deferred +} diff --git a/coroutines/src/jvmTest/kotlin/dev/inmo/micro_utils/coroutines/WeakJob.kt b/coroutines/src/jvmTest/kotlin/dev/inmo/micro_utils/coroutines/WeakJob.kt new file mode 100644 index 00000000000..311b3b05b3b --- /dev/null +++ b/coroutines/src/jvmTest/kotlin/dev/inmo/micro_utils/coroutines/WeakJob.kt @@ -0,0 +1,40 @@ +package dev.inmo.micro_utils.coroutines + +import kotlinx.coroutines.* +import org.junit.Test + +class WeakJob { + @Test + fun `test that weak jobs works correctly`() { + val scope = CoroutineScope(Dispatchers.Default) + lateinit var weakLaunchJob: Job + lateinit var weakAsyncJob: Job + scope.launchSynchronously { + val completeDeferred = Job() + coroutineScope { + weakLaunchJob = weakLaunch { + while (isActive) { + delay(100L) + } + } + weakAsyncJob = weakAsync { + while (isActive) { + delay(100L) + } + } + + coroutineContext.job.invokeOnCompletion { + scope.launch { + delay(1000L) + completeDeferred.complete() + } + } + launch { delay(1000L); cancel() } + } + completeDeferred.join() + } + + assert(!weakLaunchJob.isActive) + assert(!weakAsyncJob.isActive) + } +}