--- 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;
-}
-