tezvyn:

Describe coroutine cancellation mechanics and cooperative suspend functions

Curated by the Tezvyn teamSource: kotlinlang.orgadvanced
Describe coroutine cancellation mechanics and cooperative suspend functions

Tests cooperative cancellation mechanics. cancel() sets a Job to cancelling; suspend functions check this at suspension points and throw CancellationException, yet a tight non-suspending loop never checks and keeps running.

WHAT THIS TESTS: Whether you understand that Kotlin coroutine cancellation is cooperative rather than preemptive. Interviewers want to see that you know cancellation happens when the coroutine checks for it, that non-suspending CPU-bound work can ignore cancellation, and that structured concurrency relies on CancellationException propagation to clean up child coroutines.

A GOOD ANSWER COVERS: Four things in order. First, calling job.cancel() moves the Job to a cancelling state; it does not forcibly stop the underlying thread. Second, standard library suspend functions like delay and awaitCancellation are cooperative because they check the Job state at suspension points and throw CancellationException if the job is no longer active. Third, a long non-suspending computation inside a loop keeps running after cancel() because it never reaches a point where the coroutine checks for cancellation. Because the Job handle allows you to check whether the coroutine is active, you can explicitly poll that state or call a standard suspending function to introduce a cancellation check. Fourth, CancellationException is a normal mechanism for unwinding the coroutine stack so finally blocks run and resources release; if you catch it, you must rethrow it so parents and siblings are cancelled too under structured concurrency.

COMMON WRONG ANSWERS: Claiming that cancel() forcibly stops the underlying thread. Saying that simply adding the suspend keyword to a function makes it automatically check for cancellation without any explicit checks. Swallowing CancellationException in a catch block without rethrowing, which breaks cancellation propagation and leaks child coroutines. Assuming that because a function suspends, it will always notice cancellation immediately even during heavy CPU work.

LIKELY FOLLOW-UPS: How would you make a CPU-intensive loop cancellable? What is the difference between checking the Job active state and using a suspending function to check cancellation? What happens if you catch CancellationException and do not rethrow it? How does cancellation propagate from a parent Job to its children? When should you wait for a cancelled coroutine to finish?

ONE CONCRETE EXAMPLE: Imagine a coroutine launched on Dispatchers.Default that computes prime numbers in a while loop doing purely local math. Calling job.cancel() on it has no effect because the loop contains no suspension points and never checks whether the Job is still active. To fix this, you could periodically check the Job active state or call a standard suspending function like delay so the coroutine has a chance to throw CancellationException. Once that exception is thrown, the stack unwinds, any finally block releases resources, and the parent can finish.

Source: kotlinlang.org

Read the original → kotlinlang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.

Describe coroutine cancellation mechanics and cooperative suspend functions · Tezvyn