src/lua_thread.c
changeset 210 05abca972db0
parent 204 7dfc3d7bd92b
child 214 0d5d46ab49d5
equal deleted inserted replaced
209:d240da5dbeb5 210:05abca972db0
     1 #include "lua_thread.h"
     1 #include "lua_thread.h"
       
     2 #include "log.h"
     2 
     3 
     3 #include <string.h>
     4 #include <string.h>
     4 #include <assert.h>
     5 #include <assert.h>
     5 
     6 
     6 #include <lua5.1/lauxlib.h>
     7 #include <lua5.1/lauxlib.h>
   162 
   163 
   163     // return true if yielded, false if done
   164     // return true if yielded, false if done
   164     return (thread->L != NULL);
   165     return (thread->L != NULL);
   165 }
   166 }
   166 
   167 
   167 void lua_thread_resume_state (lua_State *L)
   168 int lua_thread_yield_state (lua_State *L)
       
   169 {
       
   170     return lua_yield(L, 0);
       
   171 }
       
   172 
       
   173 static int _lua_thread_resume_state (lua_State *L)
   168 {
   174 {
   169     struct lua_thread *thread;
   175     struct lua_thread *thread;
   170     error_t err;
   176     error_t err;
   171     int ret;
   177     int ret;
   172 
   178 
       
   179     // pop irrelevant context arg
       
   180     lua_pop(L, 1);
       
   181 
   173     // lookup the thread's context
   182     // lookup the thread's context
   174     lua_pushthread(L);
   183     lua_pushthread(L);
   175     lua_gettable(L, LUA_REGISTRYINDEX);
   184     lua_gettable(L, LUA_REGISTRYINDEX);
       
   185     
       
   186     // not registered?
       
   187     if (lua_isnil(L, -1))
       
   188         return luaL_error(L, "not a registered lua_thread state");
       
   189 
       
   190     else if (lua_isboolean(L, -1) && !lua_toboolean(L, -1))
       
   191         return luaL_error(L, "lua_thread was aborted");
   176 
   192 
   177     // get it as a pointer
   193     // get it as a pointer
   178     if ((thread = lua_touserdata(L, -1)) == NULL)
   194     if ((thread = lua_touserdata(L, -1)) == NULL)
   179         luaL_error(L, "lua_thread_resume_state: lua_touserdata");
   195         return luaL_error(L, "lua_touserdata");
       
   196     else
       
   197         lua_pop(L, 1);
   180 
   198 
   181     // handle the resume
   199     // handle the resume
   182     if ((ret = lua_thread_resume(L, thread, &err)) < 0)
   200     if ((ret = lua_thread_resume(L, thread, &err)) < 0)
   183         // notify user
   201         // notify user
   184         return lua_thread_done(thread->L, thread, &err);
   202         lua_thread_done(thread->L, thread, &err);
   185 
   203 
   186     // finished?
   204     // finished?
   187     if (ret == 0)
   205     else if (ret == 0)
   188         return lua_thread_done(thread->L, thread, NULL);
   206         lua_thread_done(thread->L, thread, NULL);
   189 }
   207 
   190 
   208     // ok
       
   209     return 0;
       
   210 }
       
   211 
       
   212 void lua_thread_resume_state (lua_State *L)
       
   213 {
       
   214     error_t err;
       
   215 
       
   216     // execute in protected mode
       
   217     if (nexus_lua_error(L, lua_cpcall(L, _lua_thread_resume_state, NULL), &err))
       
   218         log_warn_error(&err, "%p", L);
       
   219 }
       
   220 
       
   221 static int _lua_thread_abort (lua_State *L)
       
   222 {
       
   223     struct lua_thread *thread;
       
   224 
       
   225     // get context arg
       
   226     if ((thread = lua_touserdata(L, -1)) == NULL)
       
   227         luaL_error(L, "lua_thread_resume_state: lua_touserdata");
       
   228     else
       
   229         lua_pop(L, 1);
       
   230 
       
   231     // no mechanism to actually abort the underlying wait yet
       
   232     (void) thread;
       
   233 
       
   234     // invalidate in registry for later lua_thread_resume_state
       
   235     lua_pushthread(L);
       
   236     lua_pushboolean(L, false);
       
   237     lua_settable(L, LUA_REGISTRYINDEX);
       
   238 
       
   239     // not much else we can do
       
   240     return 0;
       
   241 }
       
   242 
       
   243 void lua_thread_abort (struct lua_thread *thread)
       
   244 {
       
   245     error_t err;
       
   246 
       
   247     if (!thread->L)
       
   248         // no thread executing
       
   249         return;
       
   250     
       
   251     // use protected mode
       
   252     if (nexus_lua_error(thread->L, lua_cpcall(thread->L, _lua_thread_abort, thread), &err))
       
   253         log_warn_error(&err, "_lua_thread_abort");
       
   254 
       
   255     // unset
       
   256     thread->L = NULL;
       
   257 }
       
   258