Hacker News new | past | comments | ask | show | jobs | submit login

> I figured most "interpreted" languages would be trivial to implement any kind of threads, because at any point the interpreter could decide to save the state of one language thread and switch to another, without bothering the interpreter's own stack.

Some language interpreters keep the "virtual" stack and the C stack separate like this, including current versions of Lua. As you suggest, this allows Lua to support coroutines which each have their own virtual stack.

However other interpreters, such as CPython, keep both stacks synchronized. In this case, a call in the interpreted language corresponds to a call in C - recursively back into the main interpreter loop. This is why Python's generators do not have independent stacks.

The awfully-named "Stackless Python" [0] breaks the synchronization between stacks, to allow Python to support stackful coroutines.

At least, the above was my understanding until recently. The upcoming Lua 5.4 changes to using a recursive call [1], like CPython, but still supports stackful coroutines. I don't know how this is implemented.

[0] https://github.com/stackless-dev/stackless

[1] https://github.com/lua/lua/commit/196c87c9cecfacf978f37de4ec...

I was curious about these changes to Lua 5.4, so I had a look. When you create a Lua coroutine that allocates 200 Lua stack frames and then yields across them, the first longjmp crosses 200ish C stack frames. When you later resume, all those C stack frames are gone, but there wasn't any important state in them! Lua just calls luaV_execute in a loop[0]. (Trampolining?) So at that point, for that coroutine, the lower 200ish Lua stack frames do not have corresponding C stack frames, but any Lua subroutines you then call will have corresponding C stack frames.

[0] https://github.com/lua/lua/blob/9b7987a9d1471ba94764286b28e0...

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact