Azur Haljeta
12/11/2020, 8:18 PMisActive
. But how to make it cooperative when you're dealing with code which doesn't include loops, i.e. when you don't have a right place to put the isActive
check?suspend fun fetchData(): Int = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
val client = OkHttpClient()
val request = Request.Builder()
.url("<http://slowwly.robertomurray.co.uk/delay/3000/url/http://www.google.co.uk>")
.build()
// the url uses a service which delays requests on purpose
val response = client.newCall(request).execute()
println("Got response ${response.code}")
response.code
}
withTimeout
below makes no sense since the code above isn't cooperative. The http request needs at least 3000 ms to complete and the timeout throws an exception after those 3 seconds, when it's too late already.
GlobalScope.launch {
withTimeout(2000L) {
fetchData()
}
}
isActive
check.Zach Klippenstein (he/him) [MOD]
12/11/2020, 8:32 PMrunInterruptable
or somethingAzur Haljeta
12/11/2020, 8:46 PMZach Klippenstein (he/him) [MOD]
12/12/2020, 1:10 AMwithTimeout
should just work in something like
withTimeout(1000) {
someBlockingCall()
}
Joris PZ
12/12/2020, 10:24 AMsomeBlockingCall
supports interruption? From the Java documentation:
What if a thread goes a long time without invoking a method that throws InterruptedException? Then it must periodically invoke Thread.interrupted, which returns true if an interrupt has been received. For example:
for (int i = 0; i < inputs.length; i++) {
heavyCrunch(inputs[i]);
if (Thread.interrupted()) {
// We've been interrupted: no more crunching.
return;
}
}
In this simple example, the code simply tests for the interrupt and exits the thread if one has been received. In more complex applications, it might make more sense to throw an InterruptedException:
if (Thread.interrupted()) {
throw new InterruptedException();
}
So if someBlockingCall
calculated Fibonacci numbers in an infinite loop without checking for Thread.interrupted()
then I don't think there's anything you can do to interrupt itAzur Haljeta
12/12/2020, 10:25 AMrunInterruptible
https://stackoverflow.com/search?q=runInterruptible
Only three questions at the time of writingJoris PZ
12/12/2020, 10:39 AMAzur Haljeta
12/12/2020, 10:41 AMwithTimeout{ }
)Joris PZ
12/12/2020, 10:43 AMAzur Haljeta
12/12/2020, 10:46 AMwithTimeout
or runInterruptible
or both – will work, as I've explained in the first 2-3 messages in this thread.
Also all of this is for learning and gaining more advanced skills with coroutines.Joris PZ
12/12/2020, 10:53 AMisActive
, then withTimeout
should just work. Your code will run until the next suspension point and be interrupted there. As far as I know, all Kotlin library suspending functions like delay
support cancellation. If you build your own suspension logic, using suspendCancellableCoroutine
(docs) will make your code properly support cancellation.
If you're calling into non-coroutine based code that blocks on either IO or computation, than you should run it on the IO dispatcher. Using runInterruptible
will work if and only if the code supports it.Azur Haljeta
12/12/2020, 11:00 AMUsingThat's the million dollar question here the whole time – how to make that code to support it. How to write it so that it plays nicely with cancellation. How to make it cooperative.will work if and only if the code supports it.runInterruptible
Joris PZ
12/12/2020, 11:18 AMThread.interrupted()
at points in your code, and returning or throwing an exception when its true
Azur Haljeta
12/12/2020, 11:26 AMJoris PZ
12/12/2020, 11:40 AMAzur Haljeta
12/12/2020, 11:42 AMZach Klippenstein (he/him) [MOD]
12/12/2020, 8:18 PM