lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Sun, May 17, 2009 at 9:32 AM, Guy Junk <guyjunkaccount@gmail.com> wrote:
> So, libraries are placed in the registry instead of the global table
> of the current thread when I call "luaL_openlibs" or "register".
>
> But, doesn't that mean the libraries are separate from the threads?
> Why would only the first thread (script) I create get access to the
> libraries and not the subsequent ones if all the libraries are in the
> common registry?

luaL_register [1] is a bit complex in this regard. It does not always
create the global table. If the library exists in package.loaded or in
the _LOADED field of the Lua registry (they are the same table), then
the old library table is reused and all functions (e.g. math.cos) are
recreated inside the table. Nothing else is done; the global field for
the library is not updated or set (e.g. _G.math). This is why you did
not see any of the libraries loaded into the second thread's global
environment.

You must use luaL_openlibs on the main state. Then you should copy its
global environment minus the functions or libraries you do not want
available to subsequent threads into a table you keep in the Registry.
You should then, again, copy this table and use lua_setfenv to give it
the appropriate environment.

You should be aware that only functions are shared among all your
threads. This means that if any of these functions happen to keep
persistent state via upvalues, the Lua registry (e.g. require), or
environments then you could run into problems with threads violating
the exclusivity you are trying to enforce.

You may find it easier to simply delete the _LOADED table from the
registry and then call luaL_openlibs for each thread. This will cause
each function to be remade and each thread environment to have a
unique library instantiation. This example function (untested) should
work well enough:

void open_lua_libraries (lua_State *L, lua_State *thread)
{
  lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); /* current _LOADED
table created in main state */
  lua_pushnil(L);
  lua_setfield(L, LUA_REGISTRYINDEX, "_LOADED"); /* delete the _LOADED table */
  luaL_openlibs(thread); /* open libraries, creates new _LOADED table */
  lua_setfield(L, LUA_REGISTRYINDEX, "_LOADED"); /* replace our
original _LOADED table */
}

> P.S. Can someone clarify to me how much of an overhead multiple
> lua_States are exactly?

There will be minimal overhead compared to opening up multiple states
using luaL_newstate.

[1] http://www.lua.org/manual/5.1/manual.html#luaL_register

-- 
-Patrick Donnelly

"Let all men know thee, but no man know thee thoroughly: Men freely
ford that see the shallows."

- Benjamin Franklin