DC_ID CScriptModule::Resume_Thread(DC_ID ThreadID) { THREAD_MAP_ITER iFind = m_Threads.find(ThreadID); if( iFind == m_Threads.end() ) { Log(LOG_SCRIPT, "Invalid Thread ID: %d\n", ThreadID); return DC_INVALID_ID; } CThread* pThread = iFind->second; // Do the resume int status = lua_resume( pThread->m_pState, NULL, 0); if(status == LUA_YIELD) { return pThread->GetID(); } else if( status == 0 ) { // Thread exited normally Destroy_Thread(pThread->GetID()); return DC_INVALID_ID; } return DC_INVALID_ID; }
CThread* CScriptModule::Create_Thread() { CThread* pThread = new CThread(); // Push this Thread obj so we can save for registry lua_pushlightuserdata( m_pLua, (void*)pThread ); // Create a new script-side thread obj pThread->m_pState = lua_newthread( m_pLua ); // Save the new script-side thread obj in the registry lua_settable( m_pLua, LUA_REGISTRYINDEX ); m_Threads.insert( THREAD_PAIR(pThread->GetID(),pThread) ); return pThread; }
DC_ID CScriptModule::Call_Threaded_Script_Method(const char* func, const char* sig, ...) { va_list vl; int narg, nres; // New Thread CThread* pNewThread = Create_Thread(); lua_State* pThread = pNewThread->m_pState; // Push the method lua_getglobal( pThread, func ); va_start(vl, sig); narg = 0; while (*sig) { switch (*sig++) { case 'd': { lua_pushnumber(pThread, va_arg(vl, double)); break; } case 'i': { lua_pushnumber(pThread, va_arg(vl, int)); break; } case 's': { lua_pushstring(pThread, va_arg(vl, char *)); break; } case '>': { goto endwhile; } default: { break; } } narg++; luaL_checkstack(pThread, 1, "Too many arguments\n"); } endwhile: nres = strlen(sig); int status = lua_resume( pThread, NULL, narg ); // Thread exited normally if( status == 0 ) { DLog(LOG_SCRIPT, "Thread exited normally\n"); } else if( status == LUA_YIELD ) { DLog(LOG_SCRIPT, "Thread yielded\n"); } else { // TODO: check the stack here string errmsg = lua_tostring( pThread, -1 ); Log( LOG_SCRIPT, "Error running thread: %s\n", errmsg.c_str() ); lua_pop( pThread, 1 ); return DC_INVALID_ID; } nres = -nres; while (*sig) { switch (*sig++) { case 'd': { if (!lua_isnumber(pThread, nres)) { DLog(LOG_SCRIPT, "Wrong result type\n"); } *va_arg(vl, double *) = lua_tonumber(pThread, nres); break; } case 'i': { if (!lua_isnumber(pThread, nres)) { DLog(LOG_SCRIPT, "Wrong result type\n"); } *va_arg(vl, int *) = (int)lua_tonumber(pThread, nres); break; } case 's': { if (!lua_isstring(pThread, nres)) { DLog(LOG_SCRIPT, "Wrong result type\n"); } *va_arg(vl, const char **) = lua_tostring(pThread, nres); break; } default: { DLog(LOG_SCRIPT, "Invalid option\n"); } } nres++; } va_end(vl); if( status ==0 ) { Destroy_Thread(pNewThread->GetID()); return DC_INVALID_ID; } else { return pNewThread->GetID(); } }