Unless there is an enclosing actor such as @MainActor you shouldnāt make any assumption on which thread it may run. As far as I understood the system is free to resume the suspended call even on the same thread it was before, but its not a guarantee. However by @David_Smith the >default< dispatch queue for the general non-isolated async execution will be a global concurrent queue. In the future we should gain more control over this through custom executors.
ouch. i assumed async/await and threads are more orthogonal and less inter-independent. does that mean it is not possible to use swift's async/await in a single-threaded application? (FTM: this is definitely possible with the promise-based async/await implementation.)
does that mean it is not possible to use swift's async/await in a
single-threaded application?
Can you be more specific about what you mean by āsingle-threaded applicationā? Very few applications on Apple platforms are truly single threaded because Appleās frameworks regularly spin up threads (either explicitly or implicitly using Dispatch).
Based on the code snippet you posted it sounds like you want to run your URLSession code async on the main actor and thatās definitely possible. However, I suspect that your main queue stuff was just a straw man and thereās more going on here.
it is understandable that system can span threads/queues under the hood. i used the term "single-threaded application" somewhat loosely. consider this example:
from the app perspective (1) -- (4) are executed on a single serial queue, so there is no need to protect a shared mutable state with mutexes or do some other synchronisation to read/modify it. furthermore if you change (5a) to (5b) - then all (0) -- (4) are executed on the main thread, as well as any other line of code of this application (i'm not talking about what system is doing internally). so speaking very loosely this is either a "two queue application" (with 5a) or a "single threaded application" (with 5b).
assuming these somewhat loose definitions is it possible to have swift async/await based application every line of code of which runs on main thread? or more generally, on the specific threads/queues that the app specifies? with promise based async-await implementation it is definitely possible (as it's just a long winded syntax sugar above callbacks and doesn't introduce it's own opinion about threads/queues).
The snippet you posted (with 5a enabled) could run into The Deallocation Problemā¢ because youāre letting references to a non-thread object (ViewController) escape into a threaded context (all the blocks you run on self.queue). IMO the best way to avoid this is to separate any threaded code out of your view controllers into a class that you know is safe to deallocate off the main thread. And that technique lines up well with Swift concurrencyās actor model. So, in your example Iād pull everything that runs on queue out into an actor, which gets you the serialisation you want while helping to avoid The Deallocation Problemā¢.
With regards your 5b case, youād generally approach this by defining all your code to run on the main actor.
Note how the thread ID (3760684) is the same in all cases.
IMPORTANT I tested this in Xcode 13.0b2 targeting the iOS 15.0 simulator. To get it to work I had to set the SWIFT_DEBUG_CONCURRENCY_ENABLE_COOPERATIVE_QUEUES environment variable, but I believe thatās because of an implementation bug rather than anything fundamentally wrong with my code.
Having said that, this stuff is moving very fast so I could be wrong (-:
Oh, one last thing: The Swift concurrency design has an affordance for something called a custom executor, which will give you more control over how actors integrate with queues (or threads). However, this isnāt yet designed, let alone implemented. If youāre curious, see Support custom executors in Swift concurrency.