So, as a library author, if you choose to create s...
# coroutines
g
So, as a library author, if you choose to create some type
MyWorkingThing: kotlinx.coroutines.Job
, what kinds of things should you do with cancellation? In my case,
MyWorkingThing
acquires a resource that I would like to synchronize on the disposal of before letting the job hit the
Compelted
state. The
Cancelling
state seems to reflect this well: if you hit
cancel()
on a job, it goes
cancelling
while it attempts to clean up its resources. The problem is cleaning up those resources is itself a long-running operation, and I cant suspend something while its being cancelled because, well, its being cancelled. Should I just block? Should I just document
MyWorkingThing
with some docs to the effect of:
hey, if you cancel a
MyWorkingThing
its going to launch some teardown jobs in global scope.
l
Here's what you can do, but just make sure cancellation doesn't imply a possible deadlock.
Copy code
try {
    doSomethingCancellable()
} finally {
    withContext(NonCancellable) {
        cancelYourStuff()
    }
}
g
the docs for
invokeOnCompletion
alarm me a little:
Note: This function is a part of internal machinery that supports parent-child hierarchies and allows for implementation of suspending functions that wait on the Job's state. This function should not be used in general application code. Implementations of CompletionHandler must be fast and lock-free.
I'm actually overriding the
onCancellation
handler for
AbstractCoroutine
, but I dont think that buys me anything. I've since updated my tests to reflect that
suspend fun kill()
will stop the task and synchronize on its release of resources, where
fun cancel()
will simply start the process of cleaning up resources and return immediately.
l
@groostav That applies to
CompletionHandler
which is a regular function, but not to the
finally
block that is still in a continuation and can attempt to suspend (though only possible with
NonCancellable
👍, or shady hacks with scopes that I don't recommend 👎).