Comment by OskarS
2 hours ago
My first question too, and I checked out the linked book [1], and sure seems like it! There's global functions like `janet_init()` and `janet_loop()` all over the place.
A language shouldn't advertise itself as "embeddable" if it does this. It means you can't have multiple interpreters, you can't use it on multiple threads, etc. GNU Guile does this too, and it's a baffling decision! For my field (audio plugins like VSTs), it means it's absolutely a no-go, because hosts can load any number of instances of your plugins and potentially run them in parallel in the same address space, they can't rely on global state like this. Each interpreter has to be separate.
Lua does this right, as does Python (as of 3.12, when they made the GIL local to each interpreter) and I think most of the JavaScript engines. And it's not hard, instead of a global `janet_init()`, just have an opaque pointer bundle all the state, like `janet_init(interpreter)`. If you want a global interpreter, just stick it in a global variable.
Janet global state is thread local;[1] janet_init() is called once per thread.
[1] official docs: https://janet-lang.org/capi/embedding.html