CancellationException behavior in Kotlin - Time & Space Complexity
When working with Kotlin coroutines, it's important to understand how cancellation affects program flow.
We want to see how the CancellationException influences the running time of coroutine code.
Analyze the time complexity of the following coroutine code snippet.
suspend fun processItems(items: List<Int>) {
for (item in items) {
if (!kotlin.coroutines.coroutineContext.isActive) throw CancellationException()
delay(10) // simulate work
println(item)
}
}
This code processes a list of items, checking for cancellation before each step.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through each item in the list.
- How many times: Once for each item in the input list.
Each item causes a check for cancellation and a small delay, so work grows with the list size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 cancellation checks + 10 delays |
| 100 | 100 cancellation checks + 100 delays |
| 1000 | 1000 cancellation checks + 1000 delays |
Pattern observation: The total work increases directly with the number of items.
Time Complexity: O(n)
This means the time grows linearly with the number of items processed.
[X] Wrong: "CancellationException makes the loop stop immediately, so time is constant."
[OK] Correct: Cancellation only stops the loop when detected; until then, all items are processed, so time depends on input size.
Understanding how cancellation affects coroutine loops helps you reason about program responsiveness and efficiency in real apps.
"What if the cancellation check was removed? How would the time complexity change?"
Practice
CancellationException in Kotlin coroutines?Solution
Step 1: Understand coroutine cancellation
CancellationException is used to stop coroutines without throwing an error that crashes the program.Step 2: Differentiate from errors
Unlike other exceptions, CancellationException signals a normal cancellation, not a failure.Final Answer:
To stop coroutines cleanly without treating it as an error -> Option AQuick Check:
CancellationException stops coroutines cleanly [OK]
- Confusing it with runtime errors
- Thinking it restarts coroutines
- Assuming it logs info automatically
CancellationException in Kotlin?Solution
Step 1: Identify exception type
CancellationException is a specific exception type used for coroutine cancellation.Step 2: Use specific catch block
To handle cancellation properly, catch CancellationException explicitly.Final Answer:
catch (CancellationException e) { /* handle */ } -> Option DQuick Check:
Catch CancellationException explicitly [OK]
- Catching only Exception hides cancellation
- Using catch (Error) which is unrelated
- Catching Throwable catches too broadly
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
try {
repeat(3) { i ->
println("Working $i...")
delay(100)
}
} catch (e: CancellationException) {
println("Cancelled!")
} finally {
println("Cleanup done.")
}
}
delay(150)
job.cancelAndJoin()
println("Done")
}Solution
Step 1: Trace coroutine execution and cancellation
The coroutine prints "Working 0..." and "Working 1..." with 100ms delay each, then cancellation occurs after 150ms.Step 2: Handle CancellationException and finally block
CancellationException is caught, printing "Cancelled!" and finally block prints "Cleanup done." before main prints "Done".Final Answer:
Working 0... Working 1... Cancelled! Cleanup done. Done -> Option AQuick Check:
CancellationException caught, cleanup runs, then Done [OK]
- Ignoring finally block output
- Assuming all repeats run before cancel
- Missing cancellation catch output
val job = launch {
try {
delay(1000)
} catch (e: Exception) {
println("Cancelled")
}
}
job.cancel()Solution
Step 1: Check exception handling
The catch block catches Exception, which includes CancellationException but does not distinguish it from other exceptions.Step 2: Understand cancellation propagation
To specifically handle cancellation without catching unrelated exceptions, catch CancellationException explicitly.Final Answer:
It catches Exception instead of CancellationException, so cancellation is not handled properly -> Option CQuick Check:
Catch CancellationException explicitly to handle cancellation [OK]
- Assuming Exception catch handles cancellation
- Thinking delay is uncancellable
- Confusing cancel() with deadlock
CancellationException to achieve this?Solution
Step 1: Understand cancellation handling best practice
CancellationException should be caught explicitly to avoid treating cancellation as failure.Step 2: Use finally block for cleanup
Cleanup code belongs in finally to ensure it runs whether coroutine completes or is cancelled.Final Answer:
Use try-catch with catch (CancellationException) to handle cancellation and run cleanup in finally -> Option BQuick Check:
Catch CancellationException and cleanup in finally [OK]
- Catching only Exception hides cancellation
- Skipping finally block for cleanup
- Relying on global handlers for cancellation
Ready to prove it?
Pass the test and this pattern moves unknown
