This content originally appeared on DEV Community and was authored by Jin Lee
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
}
}
-
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 callscontinuation.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)
This content originally appeared on DEV Community and was authored by Jin Lee