How to avoid cascading async functions?

That’s a risky antipattern. If your sync_meets_async function is ever called from Swift’s global concurrent pool (for example, from an actor or async function, even indirectly), you will be blocking one of the finite number of threads in that pool on the expectation that another one of the threads will perform some computation later. While you might not notice any negative effects of this when using the pattern only occasionally, it can deadlock your app or server. Unlike GCD, which expects that people may do this kind of thing and allows a concurrent queue to have more threads than there are logical cores on the system, Swift concurrency requires that you never block one task on the expectation of future work occurring on another task (but offers await as a way for you to do so safely without blocking a thread). So if you fill all of the threads in the global concurrent pool with tasks that are blocking on future async work using a semaphore, none of that async work can ever be scheduled.

5 Likes