# HG changeset patch # User Tero Marttila # Date 1242914202 -10800 # Node ID 05abca972db09969ad2de26b3b0d97436f5769de # Parent d240da5dbeb52374fa53aecda12361f9055221c8 implement lua_thread_abort, add lua_thread_yield_state func, and fix lua_thread_resume_state to use protected mode diff -r d240da5dbeb5 -r 05abca972db0 src/lua_thread.c --- a/src/lua_thread.c Thu May 21 16:55:56 2009 +0300 +++ b/src/lua_thread.c Thu May 21 16:56:42 2009 +0300 @@ -1,4 +1,5 @@ #include "lua_thread.h" +#include "log.h" #include #include @@ -164,27 +165,94 @@ return (thread->L != NULL); } -void lua_thread_resume_state (lua_State *L) +int lua_thread_yield_state (lua_State *L) +{ + return lua_yield(L, 0); +} + +static int _lua_thread_resume_state (lua_State *L) { struct lua_thread *thread; error_t err; int ret; + // pop irrelevant context arg + lua_pop(L, 1); + // lookup the thread's context lua_pushthread(L); lua_gettable(L, LUA_REGISTRYINDEX); + + // not registered? + if (lua_isnil(L, -1)) + return luaL_error(L, "not a registered lua_thread state"); + + else if (lua_isboolean(L, -1) && !lua_toboolean(L, -1)) + return luaL_error(L, "lua_thread was aborted"); // get it as a pointer if ((thread = lua_touserdata(L, -1)) == NULL) - luaL_error(L, "lua_thread_resume_state: lua_touserdata"); + return luaL_error(L, "lua_touserdata"); + else + lua_pop(L, 1); // handle the resume if ((ret = lua_thread_resume(L, thread, &err)) < 0) // notify user - return lua_thread_done(thread->L, thread, &err); + lua_thread_done(thread->L, thread, &err); // finished? - if (ret == 0) - return lua_thread_done(thread->L, thread, NULL); + else if (ret == 0) + lua_thread_done(thread->L, thread, NULL); + + // ok + return 0; } +void lua_thread_resume_state (lua_State *L) +{ + error_t err; + + // execute in protected mode + if (nexus_lua_error(L, lua_cpcall(L, _lua_thread_resume_state, NULL), &err)) + log_warn_error(&err, "%p", L); +} + +static int _lua_thread_abort (lua_State *L) +{ + struct lua_thread *thread; + + // get context arg + if ((thread = lua_touserdata(L, -1)) == NULL) + luaL_error(L, "lua_thread_resume_state: lua_touserdata"); + else + lua_pop(L, 1); + + // no mechanism to actually abort the underlying wait yet + (void) thread; + + // invalidate in registry for later lua_thread_resume_state + lua_pushthread(L); + lua_pushboolean(L, false); + lua_settable(L, LUA_REGISTRYINDEX); + + // not much else we can do + return 0; +} + +void lua_thread_abort (struct lua_thread *thread) +{ + error_t err; + + if (!thread->L) + // no thread executing + return; + + // use protected mode + if (nexus_lua_error(thread->L, lua_cpcall(thread->L, _lua_thread_abort, thread), &err)) + log_warn_error(&err, "_lua_thread_abort"); + + // unset + thread->L = NULL; +} + diff -r d240da5dbeb5 -r 05abca972db0 src/lua_thread.h --- a/src/lua_thread.h Thu May 21 16:55:56 2009 +0300 +++ b/src/lua_thread.h Thu May 21 16:56:42 2009 +0300 @@ -62,9 +62,24 @@ int lua_thread_start (struct lua_thread *thread, const char *chunk, error_t *err); /** - * Protected-mode function to resume execution of the given lua_State, which must be a lua_State created with + * Protected-mode function to yield execution of the given lua_State, which must be a luaState created with * lua_thread_start. + * + * This should be called the same way as lua_yield, except no results are supported yet. + */ +int lua_thread_yield_state (lua_State *L); + +/** + * Resume execution of the given lua_State, which must be a lua_State created with lua_thread_start. */ void lua_thread_resume_state (lua_State *L); +/** + * Abort execution of the given thread, if it's running. + * + * Currently, there is no mechanism to actually abort a running thread, so this will instead release the lua_thread for + * new use, and then cause the lua_thread_resume to do nothing. + */ +void lua_thread_abort (struct lua_thread *thread); + #endif