src/lua_thread.c
branchnew-lib-errors
changeset 218 5229a5d098b2
parent 217 7728d6ec3abf
child 219 cefec18b8268
--- a/src/lua_thread.c	Wed May 27 23:57:48 2009 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-#include "lua_thread.h"
-#include "log.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include <lua5.1/lauxlib.h>
-
-
-void lua_thread_init (struct lua_thread *thread, struct nexus_lua *lua, lua_thread_cb cb_func, void *cb_arg)
-{
-    // zero
-    memset(thread, 0, sizeof(*thread));
-
-    // store
-    thread->lua = lua;
-    thread->cb_func = cb_func;
-    thread->cb_arg = cb_arg;
-}
-
-/**
- * Thread completed, cleanup and call user callback with given error (NULL for success).
- */
-static void lua_thread_done (struct lua_thread *thread, error_t *err)
-{
-    // remove from registry so thread can be GC'd
-    // XXX: unsafe
-    lua_pushthread(thread->L);
-    lua_pushnil(thread->L);
-    lua_settable(thread->L, LUA_REGISTRYINDEX);
-
-    // drop our ref
-    thread->L = NULL;
-
-    // call
-    thread->cb_func(err, thread->cb_arg);
-}
-
-/**
- * Execute the lua_resume with zero arguments. If the thread finished, this returns zero, if it yielded, >0. For
- * errors, returns -err_t.
- */
-static int lua_thread_resume (lua_State *L, struct lua_thread *thread, error_t *err)
-{
-    int ret;
-
-    (void) thread;
-    
-    // invoke it
-    switch ((ret = lua_resume(L, 0))) {
-        case LUA_YIELD:
-            // ok, running, wait
-            return 1;
-
-        case 0:
-            // done
-            return 0;
-
-        default:
-            // let caller handle
-            // XXX: backtrace...
-            return -nexus_lua_error(L, ret, err);
-    }
-}
-
-struct lua_thread_start_ctx {
-    struct lua_thread *thread;
-    const char *chunk;
-};
-
-/**
- * Create a new thread, set it up, and run the initial resume, returning the boolean result of that
- * (true for yielded, false for done).
- */
-static int _lua_thread_start (lua_State *L)
-{
-    struct lua_thread_start_ctx *ctx;
-    lua_State *TL;
-    error_t err;
-    int ret;
-
-    // read the ctx argument off the stack
-    if ((ctx = lua_touserdata(L, 1)) == NULL)
-        return luaL_error(L, "lua_touserdata");
-    else
-        lua_pop(L, 1);
-    
-    // check
-    assert(!ctx->thread->L);
-
-    // create new thread
-    TL = lua_newthread(L);
- 
-    // push the lua_thread as the value
-    lua_pushlightuserdata(L, ctx->thread);
-
-    // store L -> lua_thread mapping in the registry
-    lua_settable(L, LUA_REGISTRYINDEX);
-
-    // load the chunk as a lua function into the thread's state
-    if (nexus_lua_error(TL, luaL_loadstring(TL, ctx->chunk), &err))
-        goto error;
-
-    // initial resume on the loaded chunk
-    if ((ret = lua_thread_resume(TL, ctx->thread, &err)) < 0)
-        goto error;
-
-    // yielded?
-    if (ret) 
-        // store
-        ctx->thread->L = TL;
-    
-    // pop thread to release for GC
-    lua_pop(L, 1);
-
-    return 0;
-        
-error:
-    // pop thread to release for GC
-    lua_pop(L, 1);
-
-    // drop ref
-    ctx->thread->L = NULL;
-
-    // pass on error
-    return luaL_error(L, "%s", error_msg(&err));
-}
-
-int lua_thread_start (struct lua_thread *thread, const char *chunk, error_t *err)
-{
-    struct lua_thread_start_ctx ctx = { thread, chunk };
-
-    // sanity-check
-    assert(!thread->L);
-
-    // use protected mode to setup
-    if (nexus_lua_error(thread->lua->st, lua_cpcall(thread->lua->st, _lua_thread_start, &ctx), err))
-        return -ERROR_CODE(err);
-
-    // return true if yielded, false if done
-    return (thread->L != NULL);
-}
-
-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, **thread_ptr;
-
-    // read the ctx argument off the stack
-    if ((thread_ptr = lua_touserdata(L, 1)) == NULL)
-        return luaL_error(L, "lua_touserdata");
-    else
-        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)
-        return luaL_error(L, "lua_touserdata");
-    else
-        lua_pop(L, 1);
-
-    // store it
-    *thread_ptr = thread;
-
-    // ok
-    return 0;
-}
-
-void lua_thread_resume_state (lua_State *L)
-{
-    struct lua_thread *thread = NULL;
-    error_t err;
-    int ret;
-
-    // execute in protected mode
-    if (nexus_lua_error(L, lua_cpcall(L, _lua_thread_resume_state, &thread), &err))
-        return log_warn_error(&err, "%p", L);
-
-    // handle the resume
-    if ((ret = lua_thread_resume(L, thread, &err)) < 0)
-        // notify user
-        lua_thread_done(thread, &err);
-
-    // finished?
-    else if (ret == 0)
-        lua_thread_done(thread, NULL);
-
-}
-
-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;
-}
-