lua-users home
lua-l archive

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


I'm working on an app where I want to maintain a pool of Lua states to make
it easy to do things like index into a variable representing a Lua table
without the caller having to worry about managing Lua states. So, for
example, something like:

    LuaObj* LuaObj::operator[]( LuaObj* index ) {
        TempLuaState state;
        lua_rawgeti( state.L, LUA_REGISTRYINDEX, this->_ref );
        lua_rawgeti( state.L, LUA_REGISTRYINDEX, index->_ref );
        lua_gettable( state.L, -2 );
        return new LuaObj( state.L, -1 );
            // Constructs a new ref to the indicated object
    }

I've also rewired Lua exceptions into native exceptions instead of
setjmp/longjmp.

Now, we come to the problem: How to write the destructor for TempLuaState.
The goal should be that it takes the lua_State* and returns it to a pool of
states for reuse. However, when it does so, it needs to clean up anything
left over in the state. Essentially, I want to get back to the state things
were in after lua_newthread without having to allocate a new thread or
garbage collect the old one. Doing a lua_settop( L, 0 ) is insufficient
because we might have actually experienced an exception while down multiple
stack frame levels -- e.g., from an __index metamethod being called in the
above code. If I used pcall or cpcall, this would happen automatically but
the code above would be a lot more awkward to write.

Any advice on how to do this legitimately with the existing APIs? Any advice
on what I would need to do as an extension to the Lua implementation? Is the
following correct or am I wildly off on how the VM data structures work?

  L->ci = L->base_ci;
  L->base = L->ci->base;
  L->nCcalls = 0;
  luaF_close(L, L->base);
  L->allowhook = 1;
  L->errfunc = 0;
  restore_stack_limit(L);

Thanks.
Mark