I don't think we should get too focused on cancellation.
It's inherently a half-measure: it's used to avoid wasting resources, but it only comes into play after you've already wasted resources. If you want to minimize waste, you're going to do better if you can minimize initiating operations that end up needing to be canceled.
Not that it isn't a useful refinement. It should be planned for. But I don't think it can be considered a critical feature out of the gate.
This is incorrect. Cancelling is not just about preventing wasted resources. It's about reacting to a change in circumstances. You can't predict ahead of time that the user will change their mind. You can't know ahead of time how long a call will block.
If you want to write an app that feels responsive, you must be able to cancel operations.
To be mediately responsive you simply abandon the operation -- that is, stop waiting and ignore any result. No need to cancel anything.
In case you're talking about rolling back an operation (you probably weren't, but just in case), canceling doesn't help there either -- not generally -- since you don't know how far the operation got before canceling, how long the cancel will take to propagate (or if it can at all), etc.
"stop waiting and ignore the result" only works if the operation is something short lived that doesn't consume many resources, eg. sending a REST request.
If the operation is expensive, that doesn't work. Say, if the user clicks a link to view a 2GB file, then changes their mind to view a different file instead, you really don't want the browser to continue downloading that 2GB file only to discard the result afterwards.
But the problem is that pretty much any operation is potentially expensive. Sending a REST request might become expensive when your phone has poor signal. All of the sudden all those "inexpensive" REST calls you just ignored are queuing up only to have their responses discarded when they arrive several seconds later, wasting bandwidth when you need it most.
If the language doesn't make cancelling easy, developers won't support cancelling -- and then you end up with unresponsive apps.
That assumes distributed environment (for example, server or microservices). CPU / memory / bandwidth is finite on client-side applications (maybe it is more Swift heavy actually) and you cannot simply stop waiting and not waste resources.
Yeah, cancellation in most systems are a "patch" (as you said, you don't know how long it will take to propagate (again, assuming distributed system, but this is less relevant when we talk about multicore system, with multicore system, that really is just about when a boolean propagated to all cores from false to true) but a necessary one and need to be integrated deep in the runtime. C# as an example, passed cancellation context (I believe in C# they called cancellation token) through all their async API as optional parameter. Maybe this is something Swift should take some inspirations from and will be beneficial for client-side developers.
Comments
I don't think we should get too focused on cancellation.
It's inherently a half-measure: it's used to avoid wasting resources, but it only comes into play after you've already wasted resources. If you want to minimize waste, you're going to do better if you can minimize initiating operations that end up needing to be canceled.
Not that it isn't a useful refinement. It should be planned for. But I don't think it can be considered a critical feature out of the gate.
This is incorrect. Cancelling is not just about preventing wasted resources. It's about reacting to a change in circumstances. You can't predict ahead of time that the user will change their mind. You can't know ahead of time how long a call will block.
If you want to write an app that feels responsive, you must be able to cancel operations.
To be mediately responsive you simply abandon the operation -- that is, stop waiting and ignore any result. No need to cancel anything.
In case you're talking about rolling back an operation (you probably weren't, but just in case), canceling doesn't help there either -- not generally -- since you don't know how far the operation got before canceling, how long the cancel will take to propagate (or if it can at all), etc.
"stop waiting and ignore the result" only works if the operation is something short lived that doesn't consume many resources, eg. sending a REST request.
If the operation is expensive, that doesn't work. Say, if the user clicks a link to view a 2GB file, then changes their mind to view a different file instead, you really don't want the browser to continue downloading that 2GB file only to discard the result afterwards.
But the problem is that pretty much any operation is potentially expensive. Sending a REST request might become expensive when your phone has poor signal. All of the sudden all those "inexpensive" REST calls you just ignored are queuing up only to have their responses discarded when they arrive several seconds later, wasting bandwidth when you need it most.
If the language doesn't make cancelling easy, developers won't support cancelling -- and then you end up with unresponsive apps.
That assumes distributed environment (for example, server or microservices). CPU / memory / bandwidth is finite on client-side applications (maybe it is more Swift heavy actually) and you cannot simply stop waiting and not waste resources.
Yeah, cancellation in most systems are a "patch" (as you said, you don't know how long it will take to propagate (again, assuming distributed system, but this is less relevant when we talk about multicore system, with multicore system, that really is just about when a boolean propagated to all cores from false to true) but a necessary one and need to be integrated deep in the runtime. C# as an example, passed cancellation context (I believe in C# they called cancellation token) through all their async API as optional parameter. Maybe this is something Swift should take some inspirations from and will be beneficial for client-side developers.