suspendCoroutine
Suspend without resume
Example of suspendCoroutine without resume.
Explanation
In this example we will not get to the After never called
since we have suspended the co-routine without ever resuming it.
Code
package com.glassthought.sandbox
import gt.sandbox.util.output.Out
import kotlin.coroutines.suspendCoroutine
val out = Out.standard()
suspend fun main() {
out.info("Before-1")
suspendCoroutine<Unit> { continuation ->
// This lambda function is called right before the suspension
// takes place.
out.infoNonSuspend(continuation.toString())
out.infoNonSuspend("Before-2")
}
out.info("After never called")
}
Command to reproduce:
gt.sandbox.checkout.commit 7a97d782ce5c34e307b0 \
&& cd "${GT_SANDBOX_REPO}"
Output:
[elapsed: 19ms][tname:main/tid:1][coroutine:unnamed] Before-1
[elapsed: 41ms][tname:main/tid:1] SafeContinuation for Continuation at com.glassthought.sandbox.MainKt.main(Main.kt:11)
[elapsed: 42ms][tname:main/tid:1] Before-2
Resume
Immediately resume
Code
package com.glassthought.sandbox
import gt.sandbox.util.output.Out
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
val out = Out.standard()
suspend fun main() {
out.info("Before-1")
suspendCoroutine<String>{ continuation ->
// This lambda function is called right before the suspension
// takes place.
out.infoNonSuspend(continuation.toString())
out.infoNonSuspend("Before-2")
// Question: where can we catch the result that we resumed with?
continuation.resume("Hello from suspended coroutine")
}
out.info("After called because we resumed")
}
Command to reproduce:
gt.sandbox.checkout.commit f9282b62d211089b4a16 \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "./gradlew run --quiet"
Recorded output of command:
[elapsed: 23ms][tname:main/tid:1][coroutine:unnamed] Before-1
[elapsed: 46ms][tname:main/tid:1] SafeContinuation for Continuation at com.glassthought.sandbox.MainKt.main(Main.kt:12)
[elapsed: 47ms][tname:main/tid:1] Before-2
[elapsed: 47ms][tname:main/tid:1][coroutine:unnamed] After called because we resumed
Resume on a thread after thread sleep
Code
package com.glassthought.sandbox
import gt.sandbox.util.output.Out
import kotlin.concurrent.thread
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
val out = Out.standard()
suspend fun main() {
out.info("Before-1")
suspendCoroutine<String> { continuation ->
// This lambda function is called right before the suspension
// takes place.
out.infoNonSuspend(continuation.toString())
out.infoNonSuspend("Before-2a")
thread {
Thread.sleep(500)
out.infoNonSuspend("Before-2b")
// Question: where can we catch the result that we resumed with?
continuation.resume("Hello from suspended coroutine")
}
}
out.info("After called because we resumed")
}
Command to reproduce:
gt.sandbox.checkout.commit 155537f9e5c8d89bd00e \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "./gradlew run --quiet"
Recorded output of command:
[elapsed: 23ms][tname:main/tid:1][coroutine:unnamed] Before-1
[elapsed: 46ms][tname:main/tid:1] SafeContinuation for Continuation at com.glassthought.sandbox.MainKt.main(Main.kt:13)
[elapsed: 47ms][tname:main/tid:1] Before-2a
[elapsed: 553ms][tname:Thread-0/tid:20] Before-2b
[elapsed: 554ms][tname:Thread-0/tid:20][coroutine:unnamed] After called because we resumed
Resume called from a scheduler executor
Code
package com.glassthought.sandbox
import gt.sandbox.util.output.Out
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
val out = Out.standard()
private val executor = Executors.newSingleThreadScheduledExecutor {
Thread(it, "my-scheduler").apply { isDaemon = true }
}
suspend fun main() {
out.info("Before-1")
suspendCoroutine<Unit> { continuation ->
// This lambda function is called right before the suspension
// takes place.
out.infoNonSuspend(continuation.toString())
out.infoNonSuspend("Before-2a")
executor.schedule({
out.infoNonSuspend("Resuming")
continuation.resume(Unit)
}, 1000, TimeUnit.MILLISECONDS)
}
out.info("After called because we resumed")
}
Command to reproduce:
gt.sandbox.checkout.commit fea7d94468e209cd1678 \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "./gradlew run --quiet"
Recorded output of command:
[elapsed: 29ms][tname:main/tid:1][coroutine:unnamed] Before-1
[elapsed: 51ms][tname:main/tid:1] SafeContinuation for Continuation at com.glassthought.sandbox.MainKt.main(Main.kt:19)
[elapsed: 52ms][tname:main/tid:1] Before-2a
[elapsed: 1057ms][tname:my-scheduler/tid:20] Resuming
[elapsed: 1058ms][tname:my-scheduler/tid:20][coroutine:unnamed] After called because we resumed
Capturing resumed value
Code
package com.glassthought.sandbox
import gt.sandbox.util.output.Out
import kotlin.concurrent.thread
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
val out = Out.standard()
suspend fun main() {
out.info("Before-1")
val valueFromCoRoutine = suspendCoroutine { continuation ->
out.infoNonSuspend("Before-2a")
thread{
Thread.sleep(500)
out.infoNonSuspend("resuming...")
continuation.resume("resumed-value")
}
}
out.info("After called. Value from co-routine: $valueFromCoRoutine")
}
Command to reproduce:
gt.sandbox.checkout.commit 7d5c25d85bef0efdbd87 \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "./gradlew run --quiet"
Recorded output of command:
[elapsed: 24ms][tname:main/tid:1][coroutine:unnamed] Before-1
[elapsed: 38ms][tname:main/tid:1] Before-2a
[elapsed: 542ms][tname:Thread-0/tid:20] resuming...
[elapsed: 545ms][tname:Thread-0/tid:20][coroutine:unnamed] After called. Value from co-routine: resumed-value
Resume with exception
Code
package com.glassthought.sandbox
import gt.sandbox.util.output.Out
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
val out = Out.standard()
class MyException(msg: String) : Throwable(msg)
suspend fun main() {
try {
suspendCoroutine<Unit> { cont ->
out.infoNonSuspend("About to resumeWithException")
cont.resumeWithException(MyException("msg-from-resumeWithException"))
}
} catch (e: MyException) {
out.info("Caught! exc-msg: " + e.message)
}
}
Command to reproduce:
gt.sandbox.checkout.commit 32ecde1f5442756e833d \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "./gradlew run --quiet"
Recorded output of command:
[elapsed: 24ms][tname:main/tid:1] About to resumeWithException
[elapsed: 38ms][tname:main/tid:1][coroutine:unnamed] Caught! exc-msg: msg-from-resumeWithException
Children