> Of course, this is not an elegant solution, as it adds one more rule to the > language, making it more complex. However, from a legacy perspective, it > seems like a minimal scar. > (to All: Please leave your opinion if you are reading this ) > Larry’s approach seems like a horrible idea to me: it increases complexity, prevents easy migration of existing code to an asynchronous model and is incredibly verbose for no good reason.
The arguments mentioned in https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/ are not good arguments at all, as they essentially propose explicitly reducing concurrency (by allowing it only within async blocks) or making it harder to use by forcing users to pass around contexts (which is even worse than function colouring https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/). This (supposedly) reduces issues with resource contention/race conditions: sure, if you don’t use concurrency or severely limit it, you will have less issues with race conditions, but that’s not an argument in favour of nurseries, that’s an argument against concurrency. Race conditions and deadlocks are possible either way when using concurrency, and the way to avoid them is to introduce synchronisation primitives (locks, mutexes similar to the ones in https://github.com/amphp/sync/, or lockfree solutions like actors, which I am a heavy user of), not bloating signatures by forcing users to pass around contexts, reducing concurrency and completely disallowing global state. Golang is the perfect example of a language that does colourless, (mostly) contextless concurrency without the need for coloured (async/await keywords) functions and other complications. Race conditions are deadlocks are avoided, like in any concurrent model, by using appropriate synchronisation primitives, and by communicating with channels (actor model) instead of sharing memory, where appropriate. Side note, I *very* much like the current approach of implicit cancellations, because they even remove the need to pass contexts to make use of cancellations, like in golang or amphp (though the RFC could use some further work regarding cancellation inheritance between fibers, but that’s a minor issue). > Yeah, so basically, you're creating the service again and again for each > coroutine if the coroutine needs to use it. This is a good solution in the > context of multitasking, but it loses in terms of performance and memory, as > well as complexity and code size, because it requires more factory classes. > ^ this Regarding backwards compatibility (especially with revolt), since I also briefly considered submitting an async RFC and thought about it a bit, I can suggest exposing an event loop interface like https://github.com/revoltphp/event-loop/blob/main/src/EventLoop.php, which would allow userland event loop implementations to simply switch to using the native event loop as backend (this’ll be especially simple to do for which is the main user of fibers, revolt, since the current implementation is clearly inspired by revolt’s event loop). Essentially, the only thing that’s needed for backwards-compatibility in most cases is an API that can be used to register onWritable, onReadable callbacks for streams and a way to register delayed (delay) tasks, to completely remove the need to invoke stream_select. I’d recommend chatting with Aaron to further discuss backwards compatibility and the overall RFC: I’ve already pinged him, he’ll chime in once he has more time to read the RFC. ~~~ To Edmond, as someone who submitted RFCs before: stand your ground, try not to listen too much to what people propose in this list, especially if it’s regarding radical changes like Larry's; avoid bloating the RFC with proposals that you do not really agree with. Regards, Daniil Gentili — Daniil Gentili - Senior software engineer Portfolio: https://daniil.it <https://daniil.it/> Telegram: https://t.me/danogentili