Maintain multiple Lua states. Return an unused one for each LUA->Get()

call.

 - this means that nested calls which use Lua in unrelated, black boxed
   ways (and so don't pass around an *L) don't share a stack; when you
   Get a new state, you're guaranteed an empty stack, and like function
   dispatches, you can use absolute stack indexes starting from 1
 - we don't have to track stack counts to sanity check it; it always starts
   at 0, so just check that the stack is empty again on Release
 - we maintain a pool of states, so Get() is still fast; we typically create
   only a couple states
This commit is contained in:
Glenn Maynard
2006-10-14 22:34:15 +00:00
parent 0c6d792648
commit 82233e2ae7
+25 -11
View File
@@ -15,6 +15,7 @@
#include <cassert>
LuaManager *LUA = NULL;
static vector<lua_State *> g_FreeStateList;
static LuaFunctionList *g_LuaFunctions = NULL;
#if defined(_MSC_VER) || defined (_XBOX)
@@ -171,6 +172,10 @@ LuaManager::LuaManager()
luaopen_debug( L );
lua_settop(L, 0); // luaopen_* pushes stuff onto the stack that we don't need
/* Store the thread pool in a table on the stack, in the main thread. */
#define THREAD_POOL 1
lua_newtable( L );
RegisterTypes();
}
@@ -178,6 +183,7 @@ LuaManager::~LuaManager()
{
lua_close( m_pLuaMain );
delete m_pLock;
g_FreeStateList.clear();
}
/* Keep track of Lua stack, and enforce that when we release Lua, the stack is
@@ -187,23 +193,31 @@ static int g_iNumStackCounts = 0;
Lua *LuaManager::Get()
{
m_pLock->Lock();
if( size_t(g_iNumStackCounts) < ARRAYLEN(g_iStackCounts) )
ASSERT( lua_gettop(m_pLuaMain) == 1 );
lua_State *pRet;
if( g_FreeStateList.empty() )
{
g_iStackCounts[g_iNumStackCounts] = lua_gettop( m_pLuaMain );
pRet = lua_newthread( m_pLuaMain );
/* Store the new thread in THREAD_POOL, so it isn't collected. */
int iLast = lua_objlen( m_pLuaMain, THREAD_POOL );
lua_rawseti( m_pLuaMain, THREAD_POOL, iLast+1 );
}
++g_iNumStackCounts;
return m_pLuaMain;
else
{
pRet = g_FreeStateList.back();
g_FreeStateList.pop_back();
}
return pRet;
}
void LuaManager::Release( Lua *&p )
{
ASSERT( p == m_pLuaMain );
ASSERT( g_iNumStackCounts != 0 );
--g_iNumStackCounts;
if( size_t(g_iNumStackCounts) < ARRAYLEN(g_iStackCounts) )
{
ASSERT( g_iStackCounts[g_iNumStackCounts] == lua_gettop(m_pLuaMain) );
}
g_FreeStateList.push_back( p );
ASSERT( lua_gettop(p) == 0 );
m_pLock->Unlock();
p = NULL;
}