File tree Expand file tree Collapse file tree
main/java/com/itsaky/androidide/utils
test/java/com/itsaky/androidide/utils Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -31,6 +31,7 @@ class KeyedDebouncingAction<T: Any>(
3131 val channel : Channel <T >,
3232 val job : Job ,
3333 ) {
34+ /* * Cancels this entry's worker job and closes its channel, in that order. */
3435 fun cancel () {
3536 // Cancel the job FIRST, then close the channel. Closing the channel first
3637 // wakes a parked receive() with a ClosedReceiveChannelException before the
@@ -55,6 +56,10 @@ class KeyedDebouncingAction<T: Any>(
5556 entry.channel.trySend(key)
5657 }
5758
59+ /* *
60+ * Creates a new [ActionEntry]: a CONFLATED channel plus a worker coroutine that debounces
61+ * incoming keys and runs [action] for the latest one, stopping cleanly when the channel is closed.
62+ */
5863 @OptIn(ExperimentalCoroutinesApi ::class )
5964 private fun createEntry (): ActionEntry <T > {
6065 val channel = Channel <T >(Channel .CONFLATED )
Original file line number Diff line number Diff line change @@ -27,6 +27,7 @@ import kotlin.time.Duration.Companion.milliseconds
2727 */
2828class KeyedDebouncingActionCancelTest {
2929
30+ /* * Cancelling an entry whose worker is parked on receive() must not surface an uncaught exception. */
3031 @Test
3132 fun `cancelling a parked worker does not leak a ClosedReceiveChannelException` () = runBlocking {
3233 val uncaught = AtomicReference <Throwable ?>(null )
You can’t perform that action at this time.
0 commit comments