How can you force cancel a task that doesn't need cleanup and doesn't check for cancellation?
If this cannot be done, would this be a useful addition to Swift?
Here is the situation:
-
The async method doesn't check for cancellation since it is not doing anything repetively (for example in a loop). For example, the method may be doing "try JSONDecoder().decode(Dictionary<String, ...>.self, from: data)" where data is a large amount.
-
The method doesn't need cleanup.
-
I would like the force cancellation to throw an error. I am already handling errors for the async method.
My intended situation if that the user request the async method to get some JSON encoded data, but since it is taking longer that they are willing to wait, they would tap a cancellation button that the app provides.
How can you force cancel a task that … doesn't check for cancellation?
You can’t.
would this be a useful addition to Swift?
Unlikely.
You’re reasoning from a false premise here. All meaningful Swift functions require some sort of cleanup. The fact that this cleanup isn’t obvious is just the compiler hiding fiddly implementation details from you. A classic example of this is ARC, where you don’t have to worry about cleaning up because the compiler is emitting all the necessary retains and releases.
Given that reality, there’s no way to stop code that doesn’t check for cancellation. Attempting to do that would leave the program in an undefined state. For example, a valid implementation of malloc
would be:
-
Lock a mutex that protects the memory allocator’s state.
-
Manipulate that state to allocate the memory.
-
Unlock the mutex.
-
Return that pointer from step 2.
If your task calls malloc
and you force stop it after step 1 and before step 3, you’ve broken the memory allocator )-:
Returning to your big picture goal, you wrote:
My intended situation if that the user request the async method to get some JSON encoded data
You need to separate CPU- and I/O-bound work. I/O-bound works should always support asynchronous cancellation. And if you’re getting this JSON data using URLSession
, it does indeed support cancellation.
In contrast, CPU-bound would only need to worry about cancellation if it’s gonna take a long time. If you’re decoding a typical REST response, that’ll be so quick that there’s no point checking for cancellation. OTOH, if you’re finding large prime numbers you need to explicitly check for cancellation.
If you have some code that doesn’t check for cancellation when it should, things get tricky. On macOS, one option is to run that code in a separate process and then kill the process when you want it to stop. That’s not possible on iOS. The best you can do is apply the ‘abandon in place’ strategy, that is, let it run but ignore the results. However, that’s not perfect because the code might be consuming significant resources.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"