From d90b00f237d764b7e3828cd492bc15a9cd373de2 Mon Sep 17 00:00:00 2001 From: "Robert G. Jakabosky" Date: Thu, 24 Mar 2011 06:06:55 -0700 Subject: [PATCH] Move low-level threads code into a different project lua-llthreads. --- .gitignore | 1 + rockspecs/lua-zmq-threads-scm-0.rockspec | 22 +++ src/thread.nobj.lua | 205 ----------------------- src/{thread.lua => threads.lua} | 9 +- zmq.nobj.lua | 1 - 5 files changed, 28 insertions(+), 210 deletions(-) create mode 100644 rockspecs/lua-zmq-threads-scm-0.rockspec delete mode 100644 src/thread.nobj.lua rename src/{thread.lua => threads.lua} (90%) diff --git a/.gitignore b/.gitignore index 884eead..c91f3f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +build *.lo *.so *.swp diff --git a/rockspecs/lua-zmq-threads-scm-0.rockspec b/rockspecs/lua-zmq-threads-scm-0.rockspec new file mode 100644 index 0000000..96db1ca --- /dev/null +++ b/rockspecs/lua-zmq-threads-scm-0.rockspec @@ -0,0 +1,22 @@ +package = "lua-zmq-threads" +version = "scm-1" +source = { + url = "git://github.com/Neopallium/lua-zmq.git" +} +description = { + summary = "Lua bindings to zeromq2, with LuaJIT2 FFI support.", + homepage = "http://github.com/Neopallium/lua-zmq", + license = "MIT/X11" +} +dependencies = { + "lua >= 5.1", + "zmq", +} +build = { + type = "builtin", + install = { + lua = { + ['zmq.threads'] = "src/threads.lua", + } + } +} diff --git a/src/thread.nobj.lua b/src/thread.nobj.lua deleted file mode 100644 index ac39369..0000000 --- a/src/thread.nobj.lua +++ /dev/null @@ -1,205 +0,0 @@ --- Copyright (c) 2011 by Robert G. Jakabosky --- --- Permission is hereby granted, free of charge, to any person obtaining a copy --- of this software and associated documentation files (the "Software"), to deal --- in the Software without restriction, including without limitation the rights --- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --- copies of the Software, and to permit persons to whom the Software is --- furnished to do so, subject to the following conditions: --- --- The above copyright notice and this permission notice shall be included in --- all copies or substantial portions of the Software. --- --- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN --- THE SOFTWARE. - -local ZMQ_Thread_type = [[ -typedef enum { - TSTATE_NONE = 0, - TSTATE_STARTED = 1<<1, - TSTATE_DETACHED = 1<<2, - TSTATE_JOINED = 1<<3, -} ZMQ_TState; - -typedef struct ZMQ_Thread { - lua_State *L; - pthread_t thread; - ZMQ_TState state; - int nargs; - int status; -} ZMQ_Thread; - -]] -object "ZMQ_Thread" { - sys_include "pthread.h", - c_source(ZMQ_Thread_type), - c_source[[ - -#include - -/* traceback() function from Lua 5.1.x source. */ -static int traceback (lua_State *L) { - if (!lua_isstring(L, 1)) /* 'message' not a string? */ - return 1; /* keep it intact */ - lua_getfield(L, LUA_GLOBALSINDEX, "debug"); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - return 1; - } - lua_getfield(L, -1, "traceback"); - if (!lua_isfunction(L, -1)) { - lua_pop(L, 2); - return 1; - } - lua_pushvalue(L, 1); /* pass error message */ - lua_pushinteger(L, 2); /* skip this function and traceback */ - lua_call(L, 2, 1); /* call debug.traceback */ - return 1; -} - -static ZMQ_Thread *thread_new() { - ZMQ_Thread *this; - - this = (ZMQ_Thread *)calloc(1, sizeof(ZMQ_Thread)); - this->state = TSTATE_NONE; - /* create new lua_State for the thread. */ - this->L = luaL_newstate(); - /* open standard libraries. */ - luaL_openlibs(this->L); - /* push traceback function as first value on stack. */ - lua_pushcfunction(this->L, traceback); - - return this; -} - -static void thread_destroy(ZMQ_Thread *this) { - lua_close(this->L); - free(this); -} - -static void *run_child_thread(void *arg) { - ZMQ_Thread *this = (ZMQ_Thread *)arg; - lua_State *L = this->L; - - this->status = lua_pcall(L, this->nargs, 0, 1); - - if(this->status != 0) { - const char *err_msg = lua_tostring(L, -1); - fprintf(stderr, "%s\n", err_msg); - fflush(stderr); - } - - return NULL; -} - -static int thread_start(ZMQ_Thread *this, int start_detached) { - int rc; - - this->state = TSTATE_STARTED | ((start_detached) ? TSTATE_DETACHED : 0); - rc = pthread_create(&(this->thread), NULL, run_child_thread, this); - if(rc != 0) return rc; - if(start_detached) { - rc = pthread_detach(this->thread); - } - return rc; -} - -]], - constructor { - var_in{ "const char *", "bootstrap_code" }, - --[[ varargs(...) ]] - c_source "pre" [[ - const char *str; - size_t str_len; - int nargs = 0; - int rc; - int top; - int n; -]], - c_source[[ - ${this} = thread_new(); - /* load bootstrap Lua code into child state. */ - rc = luaL_loadbuffer(${this}->L, ${bootstrap_code}, ${bootstrap_code_len}, ${bootstrap_code}); - if(rc != 0) { - /* copy error message to parent state. */ - str = lua_tolstring(${this}->L, -1, &(str_len)); - if(str != NULL) { - lua_pushlstring(L, str, str_len); - } else { - /* non-string error message. */ - lua_pushfstring(L, "luaL_loadbuffer() failed to luad bootstrap code: rc=%d", rc); - } - thread_destroy(${this}); - return lua_error(L); - } - /* copy extra args from main state to child state. */ - top = lua_gettop(L); - /* skip the bootstrap code. */ - for(n = ${bootstrap_code::idx} + 1; n <= top; n++) { - /* only support string/number/boolean/nil/lightuserdata. */ - switch(lua_type(L, n)) { - case LUA_TNIL: - lua_pushnil(${this}->L); - break; - case LUA_TNUMBER: - lua_pushnumber(${this}->L, lua_tonumber(L, n)); - break; - case LUA_TBOOLEAN: - lua_pushboolean(${this}->L, lua_toboolean(L, n)); - break; - case LUA_TSTRING: - str = lua_tolstring(L, n, &(str_len)); - lua_pushlstring(${this}->L, str, str_len); - break; - case LUA_TLIGHTUSERDATA: - lua_pushlightuserdata(${this}->L, lua_touserdata(L, n)); - break; - case LUA_TTABLE: - case LUA_TFUNCTION: - case LUA_TUSERDATA: - case LUA_TTHREAD: - default: - return luaL_argerror(L, n, - "Only nil/number/boolean/string/lightuserdata values are supported"); - } - ++nargs; - } - ${this}->nargs = nargs; -]] - }, - destructor { - c_source[[ - /* We still own the thread object iff the thread was not started or we have joined the thread. */ - if(${this}->state == TSTATE_NONE || ${this}->state == TSTATE_JOINED) { - thread_destroy(${this}); - } -]] - }, - method "start" { - var_in{ "bool", "start_detached", is_optional = true, default = 0 }, - var_out{ "int", "rc" }, - c_source[[ - if(${this}->state != TSTATE_NONE) { - return luaL_error(L, "Thread already started."); - } - ${rc} = thread_start(${this}, ${start_detached}); -]] - }, - method "join" { - var_out{ "int", "rc" }, - c_source[[ - if((${this}->state & TSTATE_STARTED) == 0) { - return luaL_error(L, "Can't join a thread that hasn't be started."); - } - ${rc} = pthread_join(${this}->thread, NULL); - /* now we own the thread object again. */ - ${this}->state = TSTATE_JOINED; -]] - }, -} - diff --git a/src/thread.lua b/src/threads.lua similarity index 90% rename from src/thread.lua rename to src/threads.lua index 30cae80..16d4305 100644 --- a/src/thread.lua +++ b/src/threads.lua @@ -19,10 +19,11 @@ -- THE SOFTWARE. -- --- zmq.thread wraps the low-level zmq.ZMQ_Thread object. +-- zmq.thread wraps the low-level threads object & a zmq context. -- local zmq = require"zmq" +local llthreads = require"llthreads" local setmetatable = setmetatable local tonumber = tonumber @@ -45,8 +46,8 @@ local func -- copy parent ZeroMQ context to this child thread. local zmq = require"zmq" -local zmq_thread = require"zmq.thread" -zmq_thread.set_parent_ctx(zmq.init_ctx(parent_ctx)) +local zthreads = require"zmq.threads" +zthreads.set_parent_ctx(zmq.init_ctx(parent_ctx)) -- create global 'arg' arg = { select(4, ...) } @@ -69,7 +70,7 @@ return func(select(4, ...)) local function new_thread(ctx, action, action_arg, ...) -- convert ZMQ_Ctx to lightuserdata. ctx = ctx:lightuserdata() - local thread = zmq.ZMQ_Thread(bootstrap_code, action, action_arg, ctx, ...) + local thread = llthreads.new(bootstrap_code, action, action_arg, ctx, ...) return setmetatable({ thread = thread, }, thread_mt) diff --git a/zmq.nobj.lua b/zmq.nobj.lua index 790ef10..cd0cdba 100644 --- a/zmq.nobj.lua +++ b/zmq.nobj.lua @@ -140,7 +140,6 @@ subfiles { "src/msg.nobj.lua", "src/socket.nobj.lua", "src/poller.nobj.lua", -"src/thread.nobj.lua", "src/ctx.nobj.lua", },