Async, Rethrows, and Defer

In Swift, unlike e.g. C#, it’s not the task itself that’s awaited. I’m pretty sure this would have to be await Task { … }.value.

1 Like

Ignoring the missing .value this does work and is the current way to have an enforced clean-up, but we have to resort to unstructured Concurrency which indicates that we are lacking a feature here. We ought to be able to express everything with structured Concurrency so that the compiler can reason about this.

Having a defer where we can opt-out of cancellation would be great.

4 Likes

Fun gotcha: In my experience, Task.sleep(nanoseconds:) returns immediately if you do that. Sleeping the current task next-to-forever seems to work with .max / 2 nanoseconds however. Maybe it's internally reinterpreting the UInt64 as signed?

(Also you probably mean to try? await that so it handles and ignores CancellationError.)

3 Likes

This would check out: setting only the MSb (i.e. (.max >> 1) + 1 or ~UInt64(Int64.max)) returns just as immediately. That should either be fixed or documented.

The source of that bug is described here: Fix bug in Dispatch executor preventing long sleeps by rauhul · Pull Request #64304 · apple/swift · GitHub but I haven't found the time to follow up on my patch.

2 Likes

It doesn't look like someone can take the helm on implementing async defer, so in the meantime I have changed all these occasions to spawning a task and waiting for it w/ semaphores. Ugly, but does the job.