diff options
Diffstat (limited to 'src/script/lua_api/l_async_events.cpp')
-rw-r--r-- | src/script/lua_api/l_async_events.cpp | 370 |
1 files changed, 0 insertions, 370 deletions
diff --git a/src/script/lua_api/l_async_events.cpp b/src/script/lua_api/l_async_events.cpp deleted file mode 100644 index f5c27a235..000000000 --- a/src/script/lua_api/l_async_events.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* -Minetest -Copyright (C) 2013 sapier, <sapier AT gmx DOT net> - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -extern "C" { -#include "lua.h" -#include "lauxlib.h" -#include "lualib.h" -int luaopen_marshal(lua_State *L); -} -#include <stdio.h> - -#include "l_async_events.h" -#include "log.h" -#include "filesys.h" -#include "porting.h" -#include "common/c_internal.h" - -/******************************************************************************/ -AsyncEngine::AsyncEngine() : - m_initDone(false), - m_JobIdCounter(0) -{ -} - -/******************************************************************************/ -AsyncEngine::~AsyncEngine() -{ - /** request all threads to stop **/ - for (std::vector<AsyncWorkerThread*>::iterator i= m_WorkerThreads.begin(); - i != m_WorkerThreads.end();i++) { - (*i)->Stop(); - } - - - /** wakeup all threads **/ - for (std::vector<AsyncWorkerThread*>::iterator i= m_WorkerThreads.begin(); - i != m_WorkerThreads.end();i++) { - m_JobQueueCounter.Post(); - } - - /** wait for threads to finish **/ - for (std::vector<AsyncWorkerThread*>::iterator i= m_WorkerThreads.begin(); - i != m_WorkerThreads.end();i++) { - (*i)->Wait(); - } - - /** force kill all threads **/ - for (std::vector<AsyncWorkerThread*>::iterator i= m_WorkerThreads.begin(); - i != m_WorkerThreads.end();i++) { - (*i)->Kill(); - delete *i; - } - - m_JobQueueMutex.Lock(); - m_JobQueue.clear(); - m_JobQueueMutex.Unlock(); - m_WorkerThreads.clear(); -} - -/******************************************************************************/ -bool AsyncEngine::registerFunction(const char* name, lua_CFunction fct) { - - if (m_initDone) return false; - m_FunctionList[name] = fct; - return true; -} - -/******************************************************************************/ -void AsyncEngine::Initialize(unsigned int numengines) { - m_initDone = true; - - for (unsigned int i=0; i < numengines; i ++) { - - AsyncWorkerThread* toadd = new AsyncWorkerThread(this,i); - m_WorkerThreads.push_back(toadd); - toadd->Start(); - } -} - -/******************************************************************************/ -unsigned int AsyncEngine::doAsyncJob(std::string fct, std::string params) { - - m_JobQueueMutex.Lock(); - LuaJobInfo toadd; - toadd.JobId = m_JobIdCounter++; - toadd.serializedFunction = fct; - toadd.serializedParams = params; - - m_JobQueue.push_back(toadd); - - m_JobQueueCounter.Post(); - - m_JobQueueMutex.Unlock(); - - return toadd.JobId; -} - -/******************************************************************************/ -LuaJobInfo AsyncEngine::getJob() { - - m_JobQueueCounter.Wait(); - m_JobQueueMutex.Lock(); - - LuaJobInfo retval; - retval.valid = false; - - if (m_JobQueue.size() != 0) { - retval = m_JobQueue.front(); - retval.valid = true; - m_JobQueue.erase((m_JobQueue.begin())); - } - m_JobQueueMutex.Unlock(); - - return retval; -} - -/******************************************************************************/ -void AsyncEngine::putJobResult(LuaJobInfo result) { - m_ResultQueueMutex.Lock(); - m_ResultQueue.push_back(result); - m_ResultQueueMutex.Unlock(); -} - -/******************************************************************************/ -void AsyncEngine::Step(lua_State *L) { - lua_pushcfunction(L, script_error_handler); - int errorhandler = lua_gettop(L); - lua_getglobal(L, "engine"); - m_ResultQueueMutex.Lock(); - while(!m_ResultQueue.empty()) { - LuaJobInfo jobdone = m_ResultQueue.front(); - m_ResultQueue.erase(m_ResultQueue.begin()); - - lua_getfield(L, -1, "async_event_handler"); - - if(lua_isnil(L, -1)) - assert("Someone managed to destroy a async callback in engine!" == 0); - - luaL_checktype(L, -1, LUA_TFUNCTION); - - lua_pushinteger(L, jobdone.JobId); - lua_pushlstring(L, jobdone.serializedResult.c_str(), - jobdone.serializedResult.length()); - - if(lua_pcall(L, 2, 0, errorhandler)) { - script_error(L); - } - } - m_ResultQueueMutex.Unlock(); - lua_pop(L, 2); // Pop engine and error handler -} - -/******************************************************************************/ -void AsyncEngine::PushFinishedJobs(lua_State* L) { - //Result Table - m_ResultQueueMutex.Lock(); - - unsigned int index=1; - lua_newtable(L); - int top = lua_gettop(L); - - while(!m_ResultQueue.empty()) { - - LuaJobInfo jobdone = m_ResultQueue.front(); - m_ResultQueue.erase(m_ResultQueue.begin()); - - lua_pushnumber(L,index); - - lua_newtable(L); - int top_lvl2 = lua_gettop(L); - - lua_pushstring(L,"jobid"); - lua_pushnumber(L,jobdone.JobId); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"retval"); - lua_pushstring(L, jobdone.serializedResult.c_str()); - lua_settable(L, top_lvl2); - - lua_settable(L, top); - index++; - } - - m_ResultQueueMutex.Unlock(); - -} -/******************************************************************************/ -void AsyncEngine::PrepareEnvironment(lua_State* L, int top) { - for(std::map<std::string,lua_CFunction>::iterator i = m_FunctionList.begin(); - i != m_FunctionList.end(); i++) { - - lua_pushstring(L,i->first.c_str()); - lua_pushcfunction(L,i->second); - lua_settable(L, top); - - } -} - -/******************************************************************************/ -int async_worker_ErrorHandler(lua_State *L) { - lua_getfield(L, LUA_GLOBALSINDEX, "debug"); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - return 1; - } - lua_getfield(L, -1, "traceback"); - if (!lua_isfunction(L, -1)) { - lua_pop(L, 2); - return 1; - } - lua_pushvalue(L, 1); - lua_pushinteger(L, 2); - lua_call(L, 2, 1); - return 1; -} - -/******************************************************************************/ -AsyncWorkerThread::AsyncWorkerThread(AsyncEngine* jobdispatcher, - unsigned int numthreadnumber) : - m_JobDispatcher(jobdispatcher), - m_luaerrorhandler(-1), - m_threadnum(numthreadnumber) -{ - // create luastack - m_LuaStack = luaL_newstate(); - - // load basic lua modules - luaL_openlibs(m_LuaStack); - - // load serialization functions - luaopen_marshal(m_LuaStack); -} - -/******************************************************************************/ -AsyncWorkerThread::~AsyncWorkerThread() { - - assert(IsRunning() == false); - lua_close(m_LuaStack); -} - -/******************************************************************************/ -void* AsyncWorkerThread::worker_thread_main() { - - //register thread for error logging - char number[21]; - snprintf(number,sizeof(number),"%d",m_threadnum); - log_register_thread(std::string("AsyncWorkerThread_") + number); - - porting::setThreadName( - std::string(std::string("AsyncWorkTh_") + number).c_str()); - - /** prepare job lua environment **/ - lua_newtable(m_LuaStack); - lua_setglobal(m_LuaStack, "engine"); - - lua_getglobal(m_LuaStack, "engine"); - int top = lua_gettop(m_LuaStack); - - lua_pushstring(m_LuaStack, DIR_DELIM); - lua_setglobal(m_LuaStack, "DIR_DELIM"); - - lua_pushstring(m_LuaStack, - std::string(porting::path_share + DIR_DELIM + "builtin").c_str()); - lua_setglobal(m_LuaStack, "SCRIPTDIR"); - - - m_JobDispatcher->PrepareEnvironment(m_LuaStack,top); - - std::string asyncscript = - porting::path_share + DIR_DELIM + "builtin" - + DIR_DELIM + "async_env.lua"; - - lua_pushcfunction(m_LuaStack, async_worker_ErrorHandler); - m_luaerrorhandler = lua_gettop(m_LuaStack); - - if(!runScript(asyncscript)) { - infostream - << "AsyncWorkderThread::worker_thread_main execution of async base environment failed!" - << std::endl; - assert("no future with broken builtin async environment scripts" == 0); - } - /** main loop **/ - while(!StopRequested()) { - //wait for job - LuaJobInfo toprocess = m_JobDispatcher->getJob(); - - if (toprocess.valid == false) { continue; } - if (StopRequested()) { continue; } - - //first push error handler - lua_pushcfunction(m_LuaStack, script_error_handler); - int errorhandler = lua_gettop(m_LuaStack); - - lua_getglobal(m_LuaStack, "engine"); - if(lua_isnil(m_LuaStack, -1)) - assert("unable to find engine within async environment" == 0); - - lua_getfield(m_LuaStack, -1, "job_processor"); - if(lua_isnil(m_LuaStack, -1)) - assert("Someone managed to destroy a async worker engine!" == 0); - - luaL_checktype(m_LuaStack, -1, LUA_TFUNCTION); - - //call it - lua_pushlstring(m_LuaStack, - toprocess.serializedFunction.c_str(), - toprocess.serializedFunction.length()); - lua_pushlstring(m_LuaStack, - toprocess.serializedParams.c_str(), - toprocess.serializedParams.length()); - - if (StopRequested()) { continue; } - if(lua_pcall(m_LuaStack, 2, 2, errorhandler)) { - script_error(m_LuaStack); - toprocess.serializedResult = "ERROR"; - } else { - //fetch result - const char *retval = lua_tostring(m_LuaStack, -2); - unsigned int lenght = lua_tointeger(m_LuaStack,-1); - toprocess.serializedResult = std::string(retval,lenght); - } - - if (StopRequested()) { continue; } - //put job result - m_JobDispatcher->putJobResult(toprocess); - } - log_deregister_thread(); - return 0; -} - -/******************************************************************************/ -bool AsyncWorkerThread::runScript(std::string script) { - - int ret = luaL_loadfile(m_LuaStack, script.c_str()) || - lua_pcall(m_LuaStack, 0, 0, m_luaerrorhandler); - if(ret){ - errorstream<<"==== ERROR FROM LUA WHILE INITIALIZING ASYNC ENVIRONMENT ====="<<std::endl; - errorstream<<"Failed to load and run script from "<<std::endl; - errorstream<<script<<":"<<std::endl; - errorstream<<std::endl; - errorstream<<lua_tostring(m_LuaStack, -1)<<std::endl; - errorstream<<std::endl; - errorstream<<"=================== END OF ERROR FROM LUA ===================="<<std::endl; - lua_pop(m_LuaStack, 1); // Pop error message from stack - lua_pop(m_LuaStack, 1); // Pop the error handler from stack - return false; - } - return true; -} - -/******************************************************************************/ -void* AsyncWorkerThread::worker_thread_wrapper(void* thread) { - return ((AsyncWorkerThread*) thread)->worker_thread_main(); -} |