<html><body><p><tt><font size="2">> From: Jan Tuitman via swift-evolution <swift-evolution@swift.org></font></tt><br><tt><font size="2">> To: swift-evolution@swift.org</font></tt><br><tt><font size="2">> Date: 08/18/2017 02:54 AM</font></tt><br><tt><font size="2">> Subject: [swift-evolution] [Concurrency] async/await + actors: cancellation</font></tt><br><tt><font size="2">> Sent by: swift-evolution-bounces@swift.org</font></tt><br><tt><font size="2">> <br>> Hi,<br>> <br>> <br>> After reading Chris Lattners proposal for async/await I wonder if <br>> the proposal has any way to cancel outstanding tasks.<br>> <br>> I saw these two:<br>> <br>> @IBAction func buttonDidClick(sender:AnyObject) {<br>> // 1<br>> beginAsync {<br>> // 2<br>> let image = await processImage()<br>> imageView.image = image<br>> }<br>> // 3<br>> } <br>> <br>> <br>> And:<br>> <br>> /// Shut down the current coroutine and give its memory back to the<br>> /// shareholders.<br>> func abandon() async -> Never {<br>> await suspendAsync { _ = $0 }<br>> }<br>> <br>> <br>> Now, if I understand this correctly, the second thing is abandoning <br>> the task from the context of the task by basically preventing the <br>> implicit callback of abandon() to ever be called.<br>> <br>> But I don't see any way how the beginAsync {} block can be canceled <br>> after a certain amount of time by the synchronous thread/context <br>> that is running at location //3<br>> <br>> shouldn't beginAsync return something which can be checked if the <br>> block passed in to it is finished/ waiting/ ...? and which has a <br>> method to cancel it?<br>> I know Thread.cancel (which existed in some programming languages) <br>> is evil because you never know where it stops, but it seems strange <br>> to me, that there is no way to communicate with the running process in //2.<br>> <br>> Then there is this example:<br>> <br>> func processImageData() async throws -> Image {<br>> startProgressBar()<br>> defer {<br>> // This will be called when error is thrown, when all operations<br>> // complete and a result is returned, or when the coroutine is<br>> // abandoned. We don't want to leave the progress bar animating if<br>> // work has stopped.<br>> stopProgressBar()<br>> }<br>> <br>> let dataResource = try await loadWebResource("dataprofile.txt")<br>> let imageResource = try await loadWebResource("imagedata.dat")<br>> do {<br>> let imageTmp = try await decodeImage(dataResource, imageResource)<br>> } catch _ as CorruptedImage {<br>> // Give up hope now.<br>> await abandon()<br>> }<br>> return try await dewarpAndCleanupImage(imageTmp)<br>> }<br>> <br>> <br>> this seems to wrap other asynchronous functions in a new async <br>> function so it can add the defer logic and abandon logic, but this <br>> seems to me only adding more checking of the spawned process and <br>> thus not sufficient enough to deal with an external reason in <br>> location //3 (for example the process running //3 receives an event <br>> that the app is about to be quitted). <br>> <br>> so I am a bit confused here, am I missing something? How would //2 <br>> be canceled from location //3, or how would //3 trigger an <br>> abandoment inside //2 ?<br>> <br></font></tt><br><tt><font size="2">My initial reading is that cancellation is not part of the async/await design. I think this is the right decision. (I hope I am right ;) ). </font></tt><br><br><tt><font size="2">First the semantics of arbitrary cancellation are problematic (as you noted); it is really hard to write reliable code when a thread of control could be spontaneously killed at any program point but the program as a whole still needs to be able to continue to operate). Second, support for cancellation imposes a significant implementation burden. It implies that you actually need to make individual tasks into real program-visible entities and that can get in the way of high-performance implementation techniques (which Chris alludes to as perhaps being needed in Swift 6/7/8 for an actor system to really become viable at scale).</font></tt><br><br><tt><font size="2">Much more reasonable to allow the programmer to plumb in cancellation where it is needed via shared state that can be checked at safely cancelable points in the task.</font></tt><br><br><tt><font size="2">regards,</font></tt><br><br><tt><font size="2">--dave</font></tt><br><BR>
</body></html>