I dont like the idea of beginAsync, suspendAsync be a standard library functions to support a language level resource.
beginAsync can be only `async` and suspendAsync can be "await resync" (something like that). Saing that, cancel a operations is not that simple! Abrupt abort any thread can leave some consequences. Usually, for network code is ok, but some other multi-thread operations is not (like calculus, drawing, file operations, etc) Timeout is not useful on mathematical operations, abort any thread which is accessing a physical device also can be dangerous (I broke one machine one time). There's no straight answer to "how" we can stop a execution block. Pause/Cancel when using a GCD queue is not that simple too! We need to remember that one of Swift's goals is to be a systems language. Not everything that is useful in "high level" is useful in "low level". Yes, coordination is important, but not a simple question to a run-time agnostic way to implement concurrency. Of course we can choose to make a run-time specific way to implement this, but i don't think is a valuable choice now. But.... return something beginAsync, suspendAsync, ever a `bool` is a good ideia (the proposal cover that too). Em seg, 28 de ago de 2017 às 22:42, Howard Lovatt via swift-evolution < swift-evolution@swift.org> escreveu: > I think this makes the proposed async/await coroutines more viable. > Building on this, if the proposed Cancelable became: > > protocol ExecutionControl { > /// Causes the executing coroutine to throw > `TerminateCoroutine.cancelled` and also terminates all the sub-coroutines. > var isCancelled: Bool { set } > > /// If an await exceeds timeout then executing task throws > `TerminateCoroutine.timeout` and also terminates all the sub-coroutines. > var timeout: DispatchTimeInterval { get set } > } > > Then async/await coroutine would have feature parity with a typical > `Future` - which would be good. > > PS Effectively the execution service is returning the `Future`! > > -- Howard. > > On 29 August 2017 at 09:42, Marc Schlichte via swift-evolution < > swift-evolution@swift.org> wrote: > >> >> Am 19.08.2017 um 20:33 schrieb Marc Schlichte via swift-evolution < >> swift-evolution@swift.org>: >> >> Hi, >> >> to support cancellation, I propose the following changes to >> `beginAsync()` and `suspendAsync()`: >> >> `beginAsync()` returns an object adhering to a `Cancelable` protocol: >> >> ``` >> func beginAsync(_ body: () async throws-> Void) rethrows -> Cancelable >> >> protocol Cancelable { func cancel() } >> ``` >> >> `suspendAsync()` takes a new thunk parameter: >> >> ``` >> func suspendAsync<T>(onCancel: () -> Void, body: (cont: (T) -> Void, err: >> (Error) -> Void) async -> T >> ``` >> >> Now, when `cancel()` is invoked, the `onCancel` thunk in the current >> suspension (if any) will be called. >> >> >> >> Example: >> >> ``` >> var task: Cancelable? >> >> @IBAction func buttonDidClick(sender: AnyObject) { >> task = beginAsync { >> do { >> let image = try await processImage() >> imageView.image = image >> } catch AsyncError.canceled { >> imageView.image = nil // or some fallback image... >> } catch { >> // other handling >> } >> } >> ) >> >> @IBAction func cancelDidClick(sender: AnyObject) { >> task?.cancel() >> } >> >> >> Just adding here that instead of directly using the low-level >> `beginAsync`, a Future/Promise could be used instead: >> >> ``` >> var task: Future<UIImage>? >> >> @IBAction func buttonDidClick(sender: AnyObject) { >> task = Future { >> try await processImage() >> } >> do { >> imageView.image = try await task!.get() >> } catch AsyncError.canceled { >> imageView.image = nil // or some fallback image... >> } catch { >> // other handling >> } >> } >> >> @iBAction func cancelDidClick(sender: AnyObject) { >> task?.cancel() >> } >> ``` >> >> Of course, the init of Future would have to be changed >> >> convenience init(_ body: () throws async -> T) { >> self.init() >> task = beginAsync { >> do { >> self.fulfill(try await body()) >> } catch { >> self.fail(error) >> } >> } >> } >> >> (BTW also added missing throws and try in code above) >> >> and `cancel()` would have to be added to `Future`: >> >> ``` >> public func cancel() { >> task?.cancel() >> } >> >> ``` >> >> >> func processImage() async throws -> UIImage { >> // This processing should be on a background queue (or better an Actor >> :-) - but ignored for this example >> var cancelled = false >> suspendAsync(onCancel: { >> >> cancelled = true >> }, body: { cont, err in >> while !done && !cancelled { >> // do the processing on image until done or canceled >> } >> guard !cancelled else { err(AsyncError.canceled) } // BTW, maybe >> change signature of `suspendAsync` to allow to throw here instead >> cont(image) >> } >> } >> ``` >> >> >> ^ BTW, this should be `return await suspendAsync(…` >> >> >> Cheers >> Marc >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution