[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: anti...require?
- From: Graham Wakefield <lists@...>
- Date: Sun, 1 Feb 2009 09:11:33 -0800
Here's what I use for this situation. You create a lua_CFunction as
the module unload handler. When the module is collected, either when
the lua_State is closed, or when the package.loaded["modulename"] is
nilled, this lua_CFunction is called.
Use it right after your luaL_register call in luaopen_x, e.g.:
luaL_register(L, "modulename", module_lib);
gc_sentinel(L, -1, module_unload_function);
/*
get a callback when the value at stack index idx is collected:
*/
static void gc_sentinel(lua_State * L, int idx, lua_CFunction
callback) {
lua_pushvalue(L, idx); // value @idx
lua_newuserdata(L, sizeof(void *)); // sentinel userdata
lua_newtable(L); // userdata metatable with __gc = callback
lua_pushcfunction(L, callback);
lua_setfield(L, -2, "__gc");
lua_setmetatable(L, -2);
/* check for (weak-valued) sentinel table; create if needed */
lua_getfield(L, LUA_REGISTRYINDEX, "gc_sentinels");
if (lua_isnoneornil(L, -1)) {
lua_pop(L, 1);
lua_newtable(L);
// make weak-keyed
lua_pushstring(L, "k");
lua_setfield(L, -2, "__mode");
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_pushvalue(L, -1);
lua_setmetatable(L, -2);
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, "gc_sentinels");
}
lua_insert(L, -3);
lua_settable(L, -3); // lua::sentinel[value @idx] = sentinel userdata
lua_pop(L, 1); // lua::sentinel
}
On Jan 31, 2009, at 11:31 AM, Luiz Henrique de Figueiredo wrote:
You cannot set __gc for tables. But you can say use a udata as
upvalue for
all functions registered in the module and then clean up when that
udata
is collected.
I have also thought about what to do in this situation and I am still
learning these tricks. Any examples would be very helpful. Thanks.
See loadlib.c, which sets __gc for library handles to tell the OS to
unload libraries from the app when they become garbage in Lua. This is
not the same technique I described above, though.