I have the following example in Swift:
func call1() { call2() }
func call2() { call3() }
func call3() { call4() }
func call4() { call5() }
func call5() { print("finish") }
If I want to make the call5() an async function, is it mandatory to change all other calls to async to make call5() to work properly?
CodePudding user response:
Calling an async
function requires a matching await
. To make it work in a sync context you need to wrap the call in a task.
Task { await call5() }
This will spawn a concurrent task on the current thread.
Here is the WWDC talk with more details about structured concurrency. https://developer.apple.com/videos/play/wwdc2021/10134/
CodePudding user response:
You don’t have to make them all async
, but you might consider doing so. Specifically, by making them all asynchronous, you enjoy two benefits:
The caller of
call1
can now know when the whole sequence is done, all the way down tocall5
.If the caller of
call1
gets canceled, structured concurrency will make sure that the cancelation is automatically propagated all the way down tocall5
.
So, you have two options:
Leave
call1
-call4
synchronous, but havecall4
invokecall5
withTask { … }
. As described above, the caller ofcall1
loses the ability to know whencall5
is done and you cannot enjoy automatic cancelation propagation:func call1() { call2() } func call2() { call3() } func call3() { call4() } func call4() { Task { await call5() } } // opts out of structured concurrency func call5() async { … }
You can make them all asynchronous, so that the caller of
call1
can know when the whole sequence is done and enjoy automatic cancelation propagation.func call1() async { await call2() } func call2() async { await call3() } func call3() async { await call4() } func call4() async { await call5() } func call5() async { … }
In short, neither approach is necessarily right or wrong: It depends upon precisely what call5
is doing asynchronously.
Also, if refactoring a legacy code base, you don’t have to jump to option 2 immediately, but rather you can start with option 1, and slowly progress to option 2 over time. See WWDC 2021 video Swift concurrency: Update a sample app for examples of how you might do this migration over time.