DEV Community

Cover image for Combining Mutex with suspendCancellableCoroutine in Kotlin
Jin Lee
Jin Lee

Posted on

Combining Mutex with suspendCancellableCoroutine in Kotlin

Recently I saw an interesting combination usage of Mutex and suspendCancellableCoroutine. This combination produces queue-like behaviour where it processes one-at-a-time in FIFO order even though there is no pop() / peek() or explicit queue data structure.

If you have used Snackbar in Jetpack Compose, you have experienced this combination already (link). SnackbarHostState.showSnackbar() is suspending and ensures only one snackbar is shown at a time.

suspend fun showSnackbar(
    message: String,
    actionLabel: String? = null,
    duration: SnackbarDuration = SnackbarDuration.Short,
): SnackbarResult =
    mutex.withLock {
        try {
            return suspendCancellableCoroutine { continuation ->
                currentSnackbarData =
                    SnackbarDataImpl(message, actionLabel, duration, continuation)
            }
        } finally {
            currentSnackbarData = null
        }
    }
Enter fullscreen mode Exit fullscreen mode
  • Mutex.withLock { ... } ensures only one caller enters the block at a time; other callers suspend and will continue in FIFO order.
  • suspendCancellableCoroutine { continuation -> ... }: suspends the caller and hands you a Continuation. Later, when the snackbar is dismissed or its action is pressed, the implementation calls continuation.resume(result) to wake the suspended caller with a SnackbarResult. If the job is cancelled meanwhile, the continuation is cancelled promptly.

Combining these, we have a queue behaviour allowing single operation (in this case snackbar) to be shown on the screen. This pairing feels like a queue because the first call must complete before the next call proceeds. However, it’s important this is not same as java.util.Queue we have seen on Java. (link)

Top comments (0)