src/lua_thread.c
changeset 215 85863b89e38b
parent 214 0d5d46ab49d5
equal deleted inserted replaced
214:0d5d46ab49d5 215:85863b89e38b
    19 }
    19 }
    20 
    20 
    21 /**
    21 /**
    22  * Thread completed, cleanup and call user callback with given error (NULL for success).
    22  * Thread completed, cleanup and call user callback with given error (NULL for success).
    23  */
    23  */
    24 static void lua_thread_done (lua_State *L, struct lua_thread *thread, error_t *err)
    24 static void lua_thread_done (struct lua_thread *thread, error_t *err)
    25 {
    25 {
    26     // remove from registry so thread can be GC'd
    26     // remove from registry so thread can be GC'd
    27     lua_pushthread(L);
    27     // XXX: unsafe
    28     lua_pushnil(L);
    28     lua_pushthread(thread->L);
    29     lua_settable(L, LUA_REGISTRYINDEX);
    29     lua_pushnil(thread->L);
       
    30     lua_settable(thread->L, LUA_REGISTRYINDEX);
    30 
    31 
    31     // drop our ref
    32     // drop our ref
    32     thread->L = NULL;
    33     thread->L = NULL;
    33 
    34 
    34     // call
    35     // call
   145     return lua_yield(L, 0);
   146     return lua_yield(L, 0);
   146 }
   147 }
   147 
   148 
   148 static int _lua_thread_resume_state (lua_State *L)
   149 static int _lua_thread_resume_state (lua_State *L)
   149 {
   150 {
   150     struct lua_thread *thread;
   151     struct lua_thread *thread, **thread_ptr;
   151     error_t err;
   152 
   152     int ret;
   153     // read the ctx argument off the stack
   153 
   154     if ((thread_ptr = lua_touserdata(L, 1)) == NULL)
   154     // pop irrelevant context arg
   155         return luaL_error(L, "lua_touserdata");
   155     lua_pop(L, 1);
   156     else
       
   157         lua_pop(L, 1);
   156 
   158 
   157     // lookup the thread's context
   159     // lookup the thread's context
   158     lua_pushthread(L);
   160     lua_pushthread(L);
   159     lua_gettable(L, LUA_REGISTRYINDEX);
   161     lua_gettable(L, LUA_REGISTRYINDEX);
   160     
   162     
   169     if ((thread = lua_touserdata(L, -1)) == NULL)
   171     if ((thread = lua_touserdata(L, -1)) == NULL)
   170         return luaL_error(L, "lua_touserdata");
   172         return luaL_error(L, "lua_touserdata");
   171     else
   173     else
   172         lua_pop(L, 1);
   174         lua_pop(L, 1);
   173 
   175 
       
   176     // store it
       
   177     *thread_ptr = thread;
       
   178 
       
   179     // ok
       
   180     return 0;
       
   181 }
       
   182 
       
   183 void lua_thread_resume_state (lua_State *L)
       
   184 {
       
   185     struct lua_thread *thread = NULL;
       
   186     error_t err;
       
   187     int ret;
       
   188 
       
   189     // execute in protected mode
       
   190     if (nexus_lua_error(L, lua_cpcall(L, _lua_thread_resume_state, &thread), &err))
       
   191         return log_warn_error(&err, "%p", L);
       
   192 
   174     // handle the resume
   193     // handle the resume
   175     if ((ret = lua_thread_resume(L, thread, &err)) < 0)
   194     if ((ret = lua_thread_resume(L, thread, &err)) < 0)
   176         // notify user
   195         // notify user
   177         lua_thread_done(thread->L, thread, &err);
   196         lua_thread_done(thread, &err);
   178 
   197 
   179     // finished?
   198     // finished?
   180     else if (ret == 0)
   199     else if (ret == 0)
   181         lua_thread_done(thread->L, thread, NULL);
   200         lua_thread_done(thread, NULL);
   182 
   201 
   183     // ok
       
   184     return 0;
       
   185 }
       
   186 
       
   187 void lua_thread_resume_state (lua_State *L)
       
   188 {
       
   189     error_t err;
       
   190 
       
   191     // execute in protected mode
       
   192     if (nexus_lua_error(L, lua_cpcall(L, _lua_thread_resume_state, NULL), &err))
       
   193         log_warn_error(&err, "%p", L);
       
   194 }
   202 }
   195 
   203 
   196 static int _lua_thread_abort (lua_State *L)
   204 static int _lua_thread_abort (lua_State *L)
   197 {
   205 {
   198     struct lua_thread *thread;
   206     struct lua_thread *thread;