Skip to content

Instantly share code, notes, and snippets.

@ilya-g
Last active December 21, 2018 06:42
Show Gist options
  • Save ilya-g/314c50369d87e0740e976818d2a09d3f to your computer and use it in GitHub Desktop.
Save ilya-g/314c50369d87e0740e976818d2a09d3f to your computer and use it in GitHub Desktop.
Cancellation support interceptor
class JobCancellationInterceptor(val originalInterceptor: ContinuationInterceptor?) :
AbstractCoroutineContextElement(ContinuationInterceptor),
ContinuationInterceptor {
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
CancellableCheckContinuation(continuation).let {
originalInterceptor?.interceptContinuation(it) ?: it
}
class CancellableCheckContinuation<T>(val continuation: Continuation<T>) : Continuation<T> {
override val context: CoroutineContext get() = continuation.context
override fun resume(value: T) {
val job = context[Job]
if (job?.isCompleted == true) {
println("Cancelling continuation, because job is already completed")
continuation.resumeWithException(job.getCompletionException())
} else {
continuation.resume(value)
}
}
override fun resumeWithException(exception: Throwable) =
continuation.resumeWithException(exception)
}
}
fun CoroutineContext.addCancellationInterceptor(): CoroutineContext = this + JobCancellationInterceptor(this[ContinuationInterceptor])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment