From 82233e2ae78a30b5470e1a0ed3ac93ac8161d70f Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Sat, 14 Oct 2006 22:34:15 +0000 Subject: [PATCH] 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 --- stepmania/src/LuaManager.cpp | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/stepmania/src/LuaManager.cpp b/stepmania/src/LuaManager.cpp index 068a3501f4..f10eda5cec 100644 --- a/stepmania/src/LuaManager.cpp +++ b/stepmania/src/LuaManager.cpp @@ -15,6 +15,7 @@ #include LuaManager *LUA = NULL; +static vector 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; }