eg

GT-Sandbox-Snapshot: Example - 1, Cancelling using SupervisorJob

Code

package com.glassthought.sandbox

import gt.sandbox.util.output.Out
import kotlinx.coroutines.*

interface Server {
  suspend fun start()
  suspend fun stop()
}

val out = Out.standard()

class ServerImpl(
  private val scope: CoroutineScope // Injected scope for better control
) : Server {

  private val job = SupervisorJob() // Ensures independent coroutines
  private val serverScope = scope + job

  override suspend fun start() {
    out.info("Starting server")

    serverScope.launch(CoroutineName("ServerWork-1")) {
      out.info("Running server work in thread: ${Thread.currentThread().name}")
      delay(2000)
      out.info("ServerWork-1 completed")
    }

    serverScope.launch(CoroutineName("ServerWork-2")) {
      out.info("Running additional server work in thread: ${Thread.currentThread().name}")
      delay(1500)
      out.info("ServerWork-2  completed")
    }
  }

  override suspend fun stop() {
    out.info("Stopping server")

    job.cancel()
  }
}

fun main() = runBlocking {
  out.info("--------------------------------------------------------------------------------")
  out.info("Example where the server is aborted prior to finishing:")
  runWithDelayBeforeStopping(1000)

  out.info("--------------------------------------------------------------------------------")
  out.info("Example where the server has time to finish:")
  runWithDelayBeforeStopping(3000)
}

private suspend fun runWithDelayBeforeStopping(delayBeforeStopping: Long) {
  val server = ServerImpl(CoroutineScope(Dispatchers.Default)) // Inject external scope
  server.start()
  delay(delayBeforeStopping) // Use delay instead of Thread.sleep
  server.stop()
}

Command to reproduce:

gt.sandbox.checkout.commit bed37c930bb1de4223cb \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "./gradlew run --quiet"

Recorded output of command:

[elapsed:   51ms][šŸ„‡/tname:main/tid:1][coroutine:unnamed] --------------------------------------------------------------------------------
[elapsed:   62ms][šŸ„‡/tname:main/tid:1][coroutine:unnamed] Example where the server is aborted prior to finishing:
[elapsed:   65ms][šŸ„‡/tname:main/tid:1][coroutine:unnamed] Starting server
[elapsed:   73ms][ā“¶/tname:DefaultDispatcher-worker-1/tid:20][coroutine:ServerWork-1] Running server work in thread: DefaultDispatcher-worker-1
[elapsed:   74ms][ā“·/tname:DefaultDispatcher-worker-2/tid:21][coroutine:ServerWork-2] Running additional server work in thread: DefaultDispatcher-worker-2
[elapsed: 1084ms][šŸ„‡/tname:main/tid:1][coroutine:unnamed] Stopping server
[elapsed: 1087ms][šŸ„‡/tname:main/tid:1][coroutine:unnamed] --------------------------------------------------------------------------------
[elapsed: 1087ms][šŸ„‡/tname:main/tid:1][coroutine:unnamed] Example where the server has time to finish:
[elapsed: 1087ms][šŸ„‡/tname:main/tid:1][coroutine:unnamed] Starting server
[elapsed: 1088ms][ā“¶/tname:DefaultDispatcher-worker-1/tid:20][coroutine:ServerWork-1] Running server work in thread: DefaultDispatcher-worker-1
[elapsed: 1088ms][ā“·/tname:DefaultDispatcher-worker-2/tid:21][coroutine:ServerWork-2] Running additional server work in thread: DefaultDispatcher-worker-2
[elapsed: 2594ms][ā“·/tname:DefaultDispatcher-worker-2/tid:21][coroutine:ServerWork-2] ServerWork-2  completed
[elapsed: 3093ms][ā“·/tname:DefaultDispatcher-worker-2/tid:21][coroutine:ServerWork-1] ServerWork-1 completed
[elapsed: 4089ms][šŸ„‡/tname:main/tid:1][coroutine:unnamed] Stopping server
Cannot re-use scope

https://chatgpt.com/share/31be55da-2e7f-4dc8-9fc3-000384f58086

Sample - 1
import kotlinx.coroutines.*

fun main() = runBlocking {
    val scope = CoroutineScope(Dispatchers.Default)

    val job = scope.launch {
        println("Job started")
        delay(1000)
        println("Job completed")
    }

    delay(500)  // Wait for a while
    scope.cancel()  // Cancel the scope

    // Attempt to launch a new job in the cancelled scope
    val newJob = scope.launch {
        println("New job started")
        delay(1000)
        println("New job completed")
    }

    newJob.invokeOnCompletion { exception ->
        if (exception is CancellationException) {
            println("New job was cancelled due to scope cancellation")
        } else if (exception != null) {
            println("New job completed with exception: $exception")
        } else {
            println("New job completed successfully")
        }
    }

    // Wait for all jobs to complete
    joinAll(job, newJob)
}
Sample - 2
import kotlinx.coroutines.*

fun main() = runBlocking {
    val scope = CoroutineScope(Dispatchers.Default)

    val job = scope.launch {
        println("Job started")
        delay(1000)
        println("Job completed")
    }

    delay(500)  // Wait for a while
    scope.cancel()  // Cancel the scope

    // Create a new scope and launch a new job
    val newScope = CoroutineScope(Dispatchers.Default)
    val newJob = newScope.launch {
        println("New job started")
        delay(1000)
        println("New job completed")
    }

    // Wait for all jobs to complete
    joinAll(job, newJob)
}


Backlinks