Skip to content

Commit

Permalink
Use TimeoutException instead of TimeoutCancellationException
Browse files Browse the repository at this point in the history
  • Loading branch information
dkhalanskyjb committed Oct 31, 2022
1 parent 98b844c commit 1de31bf
Show file tree
Hide file tree
Showing 24 changed files with 76 additions and 52 deletions.
1 change: 1 addition & 0 deletions kotlinx-coroutines-core/common/src/JobSupport.kt
Expand Up @@ -260,6 +260,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren
val firstNonCancellation = exceptions.firstOrNull { it !is CancellationException }
if (firstNonCancellation != null) return firstNonCancellation
val first = exceptions[0]
@Suppress("DEPRECATION")
if (first is TimeoutCancellationException) {
val detailedTimeoutException = exceptions.firstOrNull { it !== first && it is TimeoutCancellationException }
if (detailedTimeoutException != null) return detailedTimeoutException
Expand Down
8 changes: 8 additions & 0 deletions kotlinx-coroutines-core/common/src/Timeout.kt
Expand Up @@ -48,6 +48,7 @@ public suspend fun <T> withTimeout(timeMillis: Long, block: suspend CoroutineSco
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
@Suppress("DEPRECATION")
if (timeMillis <= 0L) throw TimeoutCancellationException("Timed out immediately")
return suspendCoroutineUninterceptedOrReturn { uCont ->
setupTimeout(TimeoutCoroutine(timeMillis, uCont), block)
Expand Down Expand Up @@ -113,6 +114,7 @@ public suspend fun <T> withTimeoutOrNull(timeMillis: Long, block: suspend Corout
if (timeMillis <= 0L) return null

var coroutine: TimeoutCoroutine<T?, T?>? = null
@Suppress("DEPRECATION")
try {
return suspendCoroutineUninterceptedOrReturn { uCont ->
val timeoutCoroutine = TimeoutCoroutine(timeMillis, uCont)
Expand Down Expand Up @@ -179,6 +181,11 @@ private class TimeoutCoroutine<U, in T: U>(
/**
* This exception is thrown by [withTimeout] to indicate timeout.
*/
@Deprecated("Use TimeoutException from the 'kotlinx-coroutines-time' package instead.",
ReplaceWith("kotlinx.coroutines.time.TimeoutException",
"kotlinx.coroutines.time"),
level = DeprecationLevel.WARNING)
@Suppress("DEPRECATION")
public class TimeoutCancellationException internal constructor(
message: String,
@JvmField @Transient internal val coroutine: Job?
Expand All @@ -195,6 +202,7 @@ public class TimeoutCancellationException internal constructor(
TimeoutCancellationException(message ?: "", coroutine).also { it.initCause(this) }
}

@Suppress("DEPRECATION")
internal fun TimeoutCancellationException(
time: Long,
coroutine: Job
Expand Down
7 changes: 4 additions & 3 deletions kotlinx-coroutines-core/common/src/flow/operators/Delay.kt
Expand Up @@ -11,6 +11,7 @@ import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.internal.*
import kotlinx.coroutines.selects.*
import kotlinx.coroutines.time.*
import kotlin.jvm.*
import kotlin.time.*

Expand Down Expand Up @@ -346,7 +347,7 @@ internal fun CoroutineScope.fixedPeriodTicker(delayMillis: Long, initialDelayMil
public fun <T> Flow<T>.sample(period: Duration): Flow<T> = sample(period.toDelayMillis())

/**
* Returns a flow that will emit a [TimeoutCancellationException] if the upstream doesn't emit an item within the given time.
* Returns a flow that will emit a [TimeoutException] if the upstream doesn't emit an item within the given time.
*
* Example:
*
Expand Down Expand Up @@ -386,7 +387,7 @@ public fun <T> Flow<T>.timeout(
private fun <T> Flow<T>.timeoutInternal(
timeout: Duration
): Flow<T> = scopedFlow { downStream ->
if (timeout <= Duration.ZERO) throw TimeoutCancellationException("Timed out immediately")
if (timeout <= Duration.ZERO) throw TimeoutException("Timed out immediately")
val values = buffer(Channel.RENDEZVOUS).produceIn(this)
whileSelect {
values.onReceiveCatching { value ->
Expand All @@ -398,7 +399,7 @@ private fun <T> Flow<T>.timeoutInternal(
return@onReceiveCatching true
}
onTimeout(timeout) {
throw TimeoutCancellationException("Timed out waiting for $timeout")
throw TimeoutException("Timed out waiting for $timeout")
}
}
}
6 changes: 4 additions & 2 deletions kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt
Expand Up @@ -27,7 +27,7 @@ internal fun <T> (suspend () -> T).startCoroutineUnintercepted(completion: Conti
* It does not use [ContinuationInterceptor] and does not update the context of the current thread.
*/
internal fun <R, T> (suspend (R) -> T).startCoroutineUnintercepted(receiver: R, completion: Continuation<T>) {
startDirect(completion) { actualCompletion ->
startDirect(completion) { actualCompletion ->
startCoroutineUninterceptedOrReturn(receiver, actualCompletion)
}
}
Expand Down Expand Up @@ -97,7 +97,9 @@ internal fun <T, R> ScopeCoroutine<T>.startUndispatchedOrReturn(receiver: R, blo
internal fun <T, R> ScopeCoroutine<T>.startUndispatchedOrReturnIgnoreTimeout(
receiver: R, block: suspend R.() -> T
): Any? {
return undispatchedResult({ e -> !(e is TimeoutCancellationException && e.coroutine === this) }) {
return undispatchedResult({ e ->
@Suppress("DEPRECATION") !(e is TimeoutCancellationException && e.coroutine === this)
}) {
block.startCoroutineUninterceptedOrReturn(receiver, this)
}
}
Expand Down
Expand Up @@ -6,6 +6,7 @@

package kotlinx.coroutines

import kotlinx.coroutines.time.*
import kotlin.test.*
import kotlin.time.*
import kotlin.time.Duration.Companion.milliseconds
Expand Down Expand Up @@ -177,7 +178,7 @@ class WithTimeoutDurationTest : TestBase() {
expectUnreached()
"OK"
}
} catch (e: TimeoutCancellationException) {
} catch (e: TimeoutException) {
assertEquals("Timed out immediately", e.message)
finish(2)
}
Expand Down
Expand Up @@ -8,6 +8,7 @@
package kotlinx.coroutines

import kotlinx.coroutines.channels.*
import kotlinx.coroutines.time.*
import kotlin.test.*
import kotlin.time.*
import kotlin.time.Duration.Companion.milliseconds
Expand Down Expand Up @@ -117,7 +118,7 @@ class WithTimeoutOrNullDurationTest : TestBase() {
}

@Test
fun testNestedTimeout() = runTest(expected = { it is TimeoutCancellationException }) {
fun testNestedTimeout() = runTest(expected = { it is TimeoutException }) {
withTimeoutOrNull(Duration.INFINITE) {
// Exception from this withTimeout is not suppressed by withTimeoutOrNull
kotlinx.coroutines.time.withTimeout(10.milliseconds) {
Expand Down
3 changes: 2 additions & 1 deletion kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt
Expand Up @@ -8,6 +8,7 @@
package kotlinx.coroutines

import kotlinx.coroutines.channels.*
import kotlinx.coroutines.time.*
import kotlin.test.*

class WithTimeoutOrNullTest : TestBase() {
Expand Down Expand Up @@ -114,7 +115,7 @@ class WithTimeoutOrNullTest : TestBase() {
}

@Test
fun testNestedTimeout() = runTest(expected = { it is TimeoutCancellationException }) {
fun testNestedTimeout() = runTest(expected = { it is TimeoutException }) {
withTimeoutOrNull(Long.MAX_VALUE) {
// Exception from this withTimeout is not suppressed by withTimeoutOrNull
kotlinx.coroutines.time.withTimeout(10) {
Expand Down
3 changes: 2 additions & 1 deletion kotlinx-coroutines-core/common/test/WithTimeoutTest.kt
Expand Up @@ -7,6 +7,7 @@

package kotlinx.coroutines

import kotlinx.coroutines.time.*
import kotlin.test.*

class WithTimeoutTest : TestBase() {
Expand Down Expand Up @@ -169,7 +170,7 @@ class WithTimeoutTest : TestBase() {
expectUnreached()
"OK"
}
} catch (e: TimeoutCancellationException) {
} catch (e: TimeoutException) {
assertEquals("Timed out immediately", e.message)
finish(2)
}
Expand Down
Expand Up @@ -6,6 +6,7 @@ package kotlinx.coroutines.flow

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.time.*
import kotlin.test.*

class ChannelFlowTest : TestBase() {
Expand Down Expand Up @@ -137,7 +138,7 @@ class ChannelFlowTest : TestBase() {

val flow = flowOf(1, 2, 3).bufferWithTimeout()
expect(1)
assertFailsWith<TimeoutCancellationException>(flow)
assertFailsWith<TimeoutException>(flow)
finish(6)
}

Expand Down
Expand Up @@ -6,6 +6,7 @@ package kotlinx.coroutines.flow

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.time.*
import kotlin.test.*
import kotlin.time.Duration.Companion.milliseconds

Expand Down Expand Up @@ -96,10 +97,10 @@ class DebounceTest : TestBase() {
}

@Test
fun testUpstreamError()= testUpstreamError(TimeoutCancellationException(""))
fun testUpstreamError()= testUpstreamError(TimeoutException(""))

@Test
fun testUpstreamErrorCancellation() = testUpstreamError(TimeoutCancellationException(""))
fun testUpstreamErrorCancellation() = testUpstreamError(TimeoutException(""))

private inline fun <reified T: Throwable> testUpstreamError(cause: T) = runTest {
val latch = Channel<Unit>()
Expand Down
Expand Up @@ -6,6 +6,7 @@ package kotlinx.coroutines.flow

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.time.*
import kotlin.test.*

class FlowOnTest : TestBase() {
Expand Down Expand Up @@ -244,7 +245,7 @@ class FlowOnTest : TestBase() {
}.flowOn(NamedDispatchers("foo")).onEach {
expect(1)
}
assertFailsWith<TimeoutCancellationException>(flow)
assertFailsWith<TimeoutException>(flow)
finish(2)
}

Expand All @@ -257,7 +258,7 @@ class FlowOnTest : TestBase() {
expect(1)
kotlinx.coroutines.time.withTimeout(-1) {}
}
assertFailsWith<TimeoutCancellationException>(flow)
assertFailsWith<TimeoutException>(flow)
finish(3)
}

Expand Down
Expand Up @@ -6,6 +6,7 @@ package kotlinx.coroutines.flow.operators

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.time.*
import kotlin.test.*
import kotlin.time.Duration.Companion.milliseconds

Expand All @@ -27,7 +28,7 @@ class TimeoutTest : TestBase() {

expect(2)
val list = mutableListOf<String>()
assertFailsWith<TimeoutCancellationException>(flow.timeout(300.milliseconds).onEach { list.add(it) })
assertFailsWith<TimeoutException>(flow.timeout(300.milliseconds).onEach { list.add(it) })
assertEquals(listOf("A", "B", "C"), list)
finish(5)
}
Expand Down Expand Up @@ -60,7 +61,7 @@ class TimeoutTest : TestBase() {

expect(2)
val list = mutableListOf<String>()
flow.timeout(300.milliseconds).catch { if (it is TimeoutCancellationException) emit("-1") }.collect { list.add(it) }
flow.timeout(300.milliseconds).catch { if (it is TimeoutException) emit("-1") }.collect { list.add(it) }
assertEquals(listOf("A", "B", "C", "-1"), list)
finish(5)
}
Expand Down Expand Up @@ -164,7 +165,7 @@ class TimeoutTest : TestBase() {
expectUnreached()
}.flowOn(NamedDispatchers("upstream")).timeout(100.milliseconds)

assertFailsWith<TimeoutCancellationException>(flow)
assertFailsWith<TimeoutException>(flow)
finish(3)
}

Expand Down Expand Up @@ -192,7 +193,7 @@ class TimeoutTest : TestBase() {
try {
MutableSharedFlow<Int>().asSharedFlow().timeout(100.milliseconds).collect()
expectUnreached()
} catch (e: TimeoutCancellationException) {
} catch (e: TimeoutException) {
finish(1)
}
}
Expand Down
@@ -1,7 +1,7 @@
kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 200 ms
kotlinx.coroutines.time.TimeoutException: Timed out waiting for 200 ms
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest.outerChildWithTimeout(StackTraceRecoveryWithTimeoutTest.kt:48)
at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest$testStacktraceIsRecoveredFromLexicalBlockWhenTriggeredByChild$1.invokeSuspend(StackTraceRecoveryWithTimeoutTest.kt:40)
Caused by: kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 200 ms
at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:116)
at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:86)
at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest.outerChildWithTimeout(StackTraceRecoveryWithTimeoutTest.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest$testStacktraceIsRecoveredFromLexicalBlockWhenTriggeredByChild$1.invokeSuspend(StackTraceRecoveryWithTimeoutTest.kt)
Caused by: kotlinx.coroutines.time.TimeoutException: Timed out waiting for 200 ms
at kotlinx.coroutines.time.TimeoutKt.TimeoutException(Timeout.kt)
at kotlinx.coroutines.time.TimeoutCoroutine.run(Timeout.kt)
@@ -1,10 +1,10 @@
kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 200 ms
kotlinx.coroutines.time.TimeoutException: Timed out waiting for 200 ms
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest.suspendForever(StackTraceRecoveryWithTimeoutTest.kt:42)
at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest$outerWithTimeout$2.invokeSuspend(StackTraceRecoveryWithTimeoutTest.kt:32)
at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest.outerWithTimeout(StackTraceRecoveryWithTimeoutTest.kt:31)
at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest$testStacktraceIsRecoveredFromSuspensionPoint$1.invokeSuspend(StackTraceRecoveryWithTimeoutTest.kt:19)
Caused by: kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 200 ms
at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:116)
at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:86)
Caused by: kotlinx.coroutines.time.TimeoutException: Timed out waiting for 200 ms
at kotlinx.coroutines.time.TimeoutKt.TimeoutException(Timeout.kt:116)
at kotlinx.coroutines.time.TimeoutCoroutine.run(Timeout.kt:86)
at kotlinx.coroutines.EventLoopImplBase$DelayedRunnableTask.run(EventLoop.common.kt:492)
@@ -1,9 +1,9 @@
kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 200 ms
kotlinx.coroutines.time.TimeoutException: Timed out waiting for 200 ms
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest.suspendForever(StackTraceRecoveryWithTimeoutTest.kt:92)
at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest$outerChild$2.invokeSuspend(StackTraceRecoveryWithTimeoutTest.kt:78)
at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest.outerChild(StackTraceRecoveryWithTimeoutTest.kt:74)
at kotlinx.coroutines.exceptions.StackTraceRecoveryWithTimeoutTest$testStacktraceIsRecoveredFromSuspensionPointWithChild$1.invokeSuspend(StackTraceRecoveryWithTimeoutTest.kt:66)
Caused by: kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 200 ms
at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:116)
at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:86)
Caused by: kotlinx.coroutines.time.TimeoutException: Timed out waiting for 200 ms
at kotlinx.coroutines.time.TimeoutKt.TimeoutException(Timeout.kt:116)
at kotlinx.coroutines.time.TimeoutCoroutine.run(Timeout.kt:86)
Expand Up @@ -5,6 +5,7 @@
package kotlinx.coroutines.exceptions

import kotlinx.coroutines.*
import kotlinx.coroutines.time.*
import org.junit.*
import org.junit.rules.*

Expand All @@ -17,7 +18,7 @@ class StackTraceRecoveryWithTimeoutTest : TestBase() {
fun testStacktraceIsRecoveredFromSuspensionPoint() = runTest {
try {
outerWithTimeout()
} catch (e: TimeoutCancellationException) {
} catch (e: TimeoutException) {
verifyStackTrace("timeout/${name.methodName}", e)
}
}
Expand All @@ -38,7 +39,7 @@ class StackTraceRecoveryWithTimeoutTest : TestBase() {
fun testStacktraceIsRecoveredFromLexicalBlockWhenTriggeredByChild() = runTest {
try {
outerChildWithTimeout()
} catch (e: TimeoutCancellationException) {
} catch (e: TimeoutException) {
verifyStackTrace("timeout/${name.methodName}", e)
}
}
Expand All @@ -64,7 +65,7 @@ class StackTraceRecoveryWithTimeoutTest : TestBase() {
fun testStacktraceIsRecoveredFromSuspensionPointWithChild() = runTest {
try {
outerChild()
} catch (e: TimeoutCancellationException) {
} catch (e: TimeoutException) {
verifyStackTrace("timeout/${name.methodName}", e)
}
}
Expand Down
Expand Up @@ -8,7 +8,7 @@ package kotlinx.coroutines.guide.exampleCancel07
import kotlinx.coroutines.*

fun main() = runBlocking {
kotlinx.coroutines.time.withTimeout(1300L) {
withTimeout(1300L) {
repeat(1000) { i ->
println("I'm sleeping $i ...")
delay(500L)
Expand Down
6 changes: 3 additions & 3 deletions kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt
Expand Up @@ -17,10 +17,10 @@ class Resource {
fun main() {
runBlocking {
repeat(100_000) { // Launch 100K coroutines
launch {
val resource = kotlinx.coroutines.time.withTimeout(60) { // Timeout of 60 ms
launch {
val resource = withTimeout(60) { // Timeout of 60 ms
delay(50) // Delay for 50 ms
Resource() // Acquire a resource and return it from withTimeout block
Resource() // Acquire a resource and return it from withTimeout block
}
resource.close() // Release the resource
}
Expand Down
8 changes: 4 additions & 4 deletions kotlinx-coroutines-core/jvm/test/guide/example-cancel-10.kt
Expand Up @@ -17,15 +17,15 @@ class Resource {
fun main() {
runBlocking {
repeat(100_000) { // Launch 100K coroutines
launch {
launch {
var resource: Resource? = null // Not acquired yet
try {
kotlinx.coroutines.time.withTimeout(60) { // Timeout of 60 ms
withTimeout(60) { // Timeout of 60 ms
delay(50) // Delay for 50 ms
resource = Resource() // Store a resource to the variable if acquired
resource = Resource() // Store a resource to the variable if acquired
}
// We can do something else with the resource here
} finally {
} finally {
resource?.close() // Release the resource if it was acquired
}
}
Expand Down

0 comments on commit 1de31bf

Please sign in to comment.