Wow, the Cosmopolitan folks have been busy: https://justine.lol/cosmo3/
The interesting part to me is:
I know, but projects like greenbean just further encourage the mindshare that async doesn't have to be the only way to do hi perf networking. Especially if normal OS threads can be made just as cheap as a stack of Futures without a special runtime like Go requires.
Also this setup might be cheap enough to do a thread per request and do a true actor model of one thread per actor. As I understand it Mummy and others still use a worker pool right? That was my impression at least. Nothing wrong with that, I just enjoy the actor model for that sorta stuff.
I found this article very insightful around the async problem: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/
What language isn’t colored?
[...] Three more languages that don’t have this problem: Go, Lua, and Ruby.
Any guess what they have in common?
Threads. Or, more precisely: multiple independent callstacks that can be switched between. It isn’t strictly necessary for them to be operating system threads. Goroutines in Go, coroutines in Lua, and fibers in Ruby are perfectly adequate.
Having used Lua a lot some time before, I can tell that it is very convenient to be able to write a function that at some points yields to another light thread. The threads are not running in parallel but you can have two processes with each their own stack passing values around to each other. It allows you to write algorithms differently. A bit like closure iterators in Nim.
Every function in the language gets to be a closure iterator that can yield back the control to the calling light-thread (a main loop for example) and the calling thread can resume when convenient the paused thread. It's all implemented using setjmp/longjmp and effectively every function in the language can be async with no effort.
If one wants to implement coroutines in pure C, setjmp and longjmp is probably not the thing to use as it does not allow to have a separate C stack for each coroutine.
One should probably use makecontext and swapcontext on stacks allocated with mmap (with MAP_GROWSDOWN, lighter than malloc). [credits to Justine from the readbean Discord]. I learned somethign new again.