Stopping/Cancelling scopes are independent of each other
Stopping/Cancelling scopes have independent cancellations
In short cancelling one co-routine scope does not cancel other co-routine scopes. Other co-routines can continue to run, if they are not cancelled.
Code
package com.glassthought.sandbox import gt.sandbox.util.output.Out import kotlinx.coroutines.* interface Server { suspend fun start() suspend fun stop() suspend fun join() } val out = Out.standard() class ServerImpl( private val serverName: String, private val scope: CoroutineScope // Injected scope for better control ) : Server { private var backgroundJob: Job? = null override suspend fun start() { out.info("Starting server") backgroundJob = scope.launch(CoroutineName("${serverName}-work-1")) { out.info("Running server work in thread: ${Thread.currentThread().name}") launch { out.info("${serverName}: spawned from background job - work-A") delay(3000) out.info("${serverName}-work-A completed") } delay(2000) out.info("${serverName}-work-1 completed") } } override suspend fun stop() { out.info("Stopping server: $serverName") scope.cancel() } override suspend fun join() { if (backgroundJob != null) { backgroundJob!!.join() } } } fun main() = runBlocking { val server1 = ServerImpl("server-1", CoroutineScope(Dispatchers.Default)) val server2 = ServerImpl("server-2", CoroutineScope(Dispatchers.Default)) server1.start() server2.start() delay(10) // Stopping server 1 should not stop server - 2 server1.stop() server1.join() server2.join() out.info("Main completed") }Command to reproduce:
gt.sandbox.checkout.commit 270036abdbf76a97afd3 \ && cd "${GT_SANDBOX_REPO}" \ && cmd.run.announce "./gradlew run --quiet"Recorded output of command:
Link to original [elapsed: 39ms][🥇/tname:main/tid:1][coroutine:unnamed] Starting server [elapsed: 57ms][🥇/tname:main/tid:1][coroutine:unnamed] Starting server [elapsed: 57ms][⓶/tname:DefaultDispatcher-worker-1/tid:20][coroutine:server-1-work-1] Running server work in thread: DefaultDispatcher-worker-1 [elapsed: 57ms][⓷/tname:DefaultDispatcher-worker-2/tid:21][coroutine:server-2-work-1] Running server work in thread: DefaultDispatcher-worker-2 [elapsed: 59ms][⓸/tname:DefaultDispatcher-worker-3/tid:22][coroutine:server-1-work-1] server-1: spawned from background job - work-A [elapsed: 59ms][⓹/tname:DefaultDispatcher-worker-4/tid:23][coroutine:server-2-work-1] server-2: spawned from background job - work-A [elapsed: 71ms][🥇/tname:main/tid:1][coroutine:unnamed] Stopping server: server-1 [elapsed: 2065ms][⓷/tname:DefaultDispatcher-worker-2/tid:21][coroutine:server-2-work-1] server-2-work-1 completed [elapsed: 3063ms][⓷/tname:DefaultDispatcher-worker-2/tid:21][coroutine:server-2-work-1] server-2-work-A completed [elapsed: 3064ms][🥇/tname:main/tid:1][coroutine:unnamed] Main completed