Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add checkCancelled() extension for Job / CoroutineContext / CoroutineScope #963

Closed
abusalimov opened this issue Jan 31, 2019 · 2 comments
Closed

Comments

@abusalimov
Copy link

Something like:

fun CoroutineContext.checkCancelled() {
    if (this[Job]?.isCancelled == true) throw job.getCancellationException()
}

AFAIK, currently the only way to explicitly check coroutine shall still proceed (at the same time throwing a proper CancellationException with a proper stack trace) is to invoke yield(), which has a check similar to the suggested one, yet marked internal:

internal fun CoroutineContext.checkCompletion() {
val job = get(Job)
if (job != null && !job.isActive) throw job.getCancellationException()
}

(Job.isCancelled is equivalent to !Job.isActive when the coroutine checks that itself).

The suggestion is to expose such extension functions for Job, CoroutineContext, CoroutineScope (similarly to isActive and cancel()).

@abusalimov abusalimov changed the title Add [Job|CoroutineContext|CoroutineScope].checkCancelled() extension functions Add checkCancelled() extension for Job / CoroutineContext / CoroutineScope Jan 31, 2019
@elizarov
Copy link
Contributor

elizarov commented Feb 1, 2019

What use-case do you envision for this function? Can you given an example code that uses this function, please.

@abusalimov
Copy link
Author

  private suspend fun <R> doExecuteCommand(command: DebuggerCommand<R>,
                                           canExecuteWhileRunning: Boolean): R {
    val expirationJob =
      if (canExecuteWhileRunning) supervisorJob
      else createSessionSuspendedSupervisorJob()
    expirationJob.checkCancelled()  // don't run if the supervisor has expired already

    return withContext(coroutineDispatcher) {
      expirationJob.cancelJobOnCompletion(coroutineContext[Job]!!)
      checkCancelled()  // check again

      command.call(this.driver)
    }
  }

  companion object {
    @Throws(CancellationException::class)
    internal fun Job.checkCancelled() {
      if (!isActive) {
        @Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
        @UseExperimental(InternalCoroutinesApi::class)  // need to get rid of this
        throw getCancellationException()
      }
    }
  }

qwwdfsad added a commit that referenced this issue Feb 27, 2019
qwwdfsad added a commit that referenced this issue Mar 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants