Skip to content

Commit bc553ba

Browse files
authored
Conditionally create an instance of CancellationException in Channel.cancel() (#2384)
Avoid creating costly exception when the channel is cancelled to save a few cycles when it's not necessary. Cancellation is heavy-enough when the channel is open, so the single check won't worsen it.
1 parent dede17e commit bc553ba

File tree

3 files changed

+3
-1
lines changed

3 files changed

+3
-1
lines changed

kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt

+1
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ internal abstract class AbstractChannel<E>(
635635
cancelInternal(cause)
636636

637637
final override fun cancel(cause: CancellationException?) {
638+
if (isClosedForReceive) return // Do not create an exception if channel is already cancelled
638639
cancelInternal(cause ?: CancellationException("$classSimpleName was cancelled"))
639640
}
640641

kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ internal open class ChannelCoroutine<E>(
2626
}
2727

2828
final override fun cancel(cause: CancellationException?) {
29+
if (isClosedForReceive) return // Do not create an exception if channel is already cancelled
2930
cancelInternal(cause ?: defaultCancellationException())
3031
}
3132

kotlinx-coroutines-core/common/src/flow/internal/Combine.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ internal fun <T1, T2, R> zipImpl(flow: Flow<T1>, flow2: Flow<T2>, transform: sus
137137
} catch (e: AbortFlowException) {
138138
e.checkOwnership(owner = this@unsafeFlow)
139139
} finally {
140-
if (!second.isClosedForReceive) second.cancel()
140+
second.cancel()
141141
}
142142
}
143143
}

0 commit comments

Comments
 (0)