-
Notifications
You must be signed in to change notification settings - Fork 0
Home
The purpose of this repository is to capture my experiments with concurrency in Swift.
The motivation is that with Structured Concurrency (Async/await), Apple and Swift Language maintainers seem to think that developers shouldn't have to worry about threads and to let the language handle it all for you.
Feels a bit patronising, but maybe true for a very large segment of developers?
Anyway, in some of my projects, I have functions that run for very long times, one such being a BASIC language interpreter, so I don't know how long it'll run, I don't know how recursive it might be (how deep the stack) and a few other invariants.
This suggests that SC is not a good choice.
Structured Concurrency seems to give you a fixed thread pool to play with, equal to the number of
hardware cores in the system. I think the main thread is also there, @MainActor
Running my BASIC code in one of these threads will severely restrict what else I can do. Especially on a machine with 1 core (or 2 like the Apple Watch).
You can't await
another function unless the function you are in is async
. This means that if
anything in my interpreter wants to do anything asynchronous (it's possible to plug in external functions)
I'd need to have the AST visitor async.
When I tried this, performance suffered, with some tests taking between 70% and 300% longer to run.
So you can avoid this and use Task {}
when you need it, but then you have no easy way to
wait for that task to complete synchronously.
You could use a semaphore or a GCD queue, or a lock, but all these are discouraged and some even banned from Swift 6.
Now my BASIC interpreter project is quite large, so I'm doing the investigations here.