0
votes

I'm designing the threading architecture for my game engine, and I have reached a point where I am stumped.

The engine is partially inspired by Grimrock's engine, where they put as much as they could into LuaJIT, with some things, including low level systems, written in C++.

This seemed like a good plan, given that LuaJIT is easy to use, and I can continue to add API functions in C++ and expand it further. Faster iteration is nice, the ability to have a custom IDE attached to the game and edit the code while it runs is an interesting option, and serializing from Lua is also easy.

But I am stumped on how to go about adding threading. I know Lua has coroutines, but that is not true threading; it's basically to keep Lua from stalling as it waits for code that takes too long.

I originally had in mind to have the main thread running in Lua and calling C++ functions which are dispatched to the scheduler, but I can't find enough information on how Lua functions. I do know that when Lua calls a C++ function it runs outside of the state, so theoretically it may be possible.

I also don't know whether, if Lua makes such a call that is not supposed to return anything, it will hang on the function until it's done.

And I'm not sure whether the task scheduler runs in the main thread, or if it is simply all worker threads pulling data from a queue.

Basically meaning that, instead of everything running at once, it waits for the game state update before doing anything.

Does anyone have any ideas, or suggestions for threading?

1
So, this question is quite broad right now. You might want to split it up into some simpler, very specific questions that an expert can unambiguously answer. The more squishy / design issues should probably go on gamedev stack exchange. - Chris Beck

1 Answers

1
votes

In general, a single lua_State * is not thread safe. It's written in pure C and meant to go very fast. It's not safe to allow exceptions go through it either. There's no locks in there and no way for it to protect itself.

If you want to run multiple lua scripts simultaneously in separate threads, the most straightforward way is to use luaL_newstate() separately in each thread, initialize each of them, and load and run scripts in each of them. They can talk to the C++ safely as long as your callbacks use locks when necessary. At least, that's how I would try to do it.

There are various things you could do to speed it up, for instance, if you are loading copies of a single script in each of the threads, you could compile it to lua bytecode before you launch any of the threads, then put the buffer into shared memory, and have the scripts load the shared byte code without changing. That's most likely an unnecessary optimization though, depending on your application.