From 92ec624951de2d344b28eb5262a3534822f6d6a7 Mon Sep 17 00:00:00 2001 From: moteus Date: Thu, 26 Dec 2013 14:34:13 +0400 Subject: Add. timeout parameter to thread:join() method --- .travis.yml | 2 ++ README.md | 3 ++ src/llthread.c | 33 ++++++++++++++++----- test/test_join_timeout.lua | 64 ++++++++++++++++++++++++++++++++++++++++ test/test_register_llthreads.lua | 12 ++++++++ 5 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 test/test_join_timeout.lua create mode 100644 test/test_register_llthreads.lua diff --git a/.travis.yml b/.travis.yml index 7bb11c6..4a28f5e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,6 +47,8 @@ script: - lua$LUA_SFX test_table_copy.lua - lua$LUA_SFX test_threads.lua - lua$LUA_SFX test_llthreads.lua + - lua$LUA_SFX test_register_llthreads.lua + - lua$LUA_SFX test_join_timeout.lua notifications: email: diff --git a/README.md b/README.md index 2ca6f36..c0b67bf 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,9 @@ This is full dropin replacement for [llthreads](https://github.com/Neopallium/lu * does not open all standart libraries (set LLTHREAD_REGISTER_STD_LIBRARY to on this feature) * register loaders for llthreads library itself +##Additional +* thread:join() method support zero timeout to check if thread alive +* thread:join() method support arbitrary timeout on Windows platform [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/moteus/lua-llthreads2/trend.png)](https://bitdeli.com/free "Bitdeli Badge") diff --git a/src/llthread.c b/src/llthread.c index 0449ea9..0f43e14 100644 --- a/src/llthread.c +++ b/src/llthread.c @@ -43,12 +43,16 @@ # define OS_THREAD_RETURT unsigned int __stdcall # define INVALID_THREAD INVALID_HANDLE_VALUE # define INFINITE_JOIN_TIMEOUT INFINITE +# define JOIN_OK 0 +# define JOIN_ETIMEDOUT 1 typedef DWORD join_timeout_t; typedef HANDLE os_thread_t; #else # define OS_THREAD_RETURT void * # define INVALID_THREAD 0 # define INFINITE_JOIN_TIMEOUT -1 +# define JOIN_OK 0 +# define JOIN_ETIMEDOUT ETIMEDOUT typedef int join_timeout_t; typedef pthread_t os_thread_t; #endif @@ -321,13 +325,15 @@ static void open_thread_libs(lua_State *L){ /* get package.preload */ lua_getglobal(L, "package"); lua_getfield(L, -1, "preload"); lua_remove(L, -2); + /*always only register*/ + lua_pushcfunction(L, luaopen_llthreads); lua_setfield(L, -2, "llthreads"); + L_REGLIB(L, io, 1); L_REGLIB(L, os, 1); L_REGLIB(L, math, 1); L_REGLIB(L, table, 1); L_REGLIB(L, debug, 1); L_REGLIB(L, string, 1); - L_REGLIB(L, llthreads, 0); lua_settop(L, top); #undef L_REGLIB @@ -482,9 +488,24 @@ static int llthread_join(llthread_t *this, join_timeout_t timeout) { } return 2; #else + int rc; + if(timeout == 0){ + rc = pthread_kill(this->thread, 0); + if(rc == 0){ /* still alive */ + rc = ETIMEDOUT; + } + if(rc == ESRCH){ /*thread dead*/ + FLAG_SET(this, TSTATE_JOINED); + rc = 0; + } + return rc; + } + + // @todo use pthread_tryjoin_np to support timeout + /* then join the thread. */ - int rc = pthread_join(this->thread, NULL); - if(rc == 0) { + rc = pthread_join(this->thread, NULL); + if((rc == 0) || (rc == ESRCH)) { FLAG_SET(this, TSTATE_JOINED); } return rc; @@ -598,7 +619,7 @@ static int l_llthread_join(lua_State *L) { } /* join the thread. */ - rc = llthread_join(this, INFINITE_JOIN_TIMEOUT); + rc = llthread_join(this, luaL_optint(L, 2, INFINITE_JOIN_TIMEOUT)); /* Push all results after the Lua code. */ if(child && FLAG_IS_SET(this, TSTATE_JOINED)) { @@ -618,13 +639,11 @@ static int l_llthread_join(lua_State *L) { return top; } -#ifndef USE_PTHREAD - if( rc == 1 ){ + if( rc == JOIN_ETIMEDOUT ){ lua_pushboolean(L, 0); lua_pushstring(L, "timeout"); return 2; } -#endif { char buf[ERROR_LEN]; diff --git a/test/test_join_timeout.lua b/test/test_join_timeout.lua new file mode 100644 index 0000000..5beac2b --- /dev/null +++ b/test/test_join_timeout.lua @@ -0,0 +1,64 @@ +local llthreads = require"llthreads" + +local sleep +local status, socket = pcall(require,"socket") +if status then + sleep = function(secs) + return socket.sleep(secs) + end +end + +if not sleep then + local status, ztimer = pcall(require, "lzmq.timer") + if status then + sleep = function(secs) + ztimer.sleep(secs * 1000) + end + end +end + +if not sleep then + sleep = function(secs) + os.execute("sleep " .. tonumber(secs)) + end +end + +local include = [[ +local llthreads = require"llthreads" + +local sleep +local status, socket = pcall(require,"socket") +if status then + sleep = function(secs) + return socket.sleep(secs) + end +end + +if not sleep then + local status, ztimer = pcall(require, "lzmq.timer") + if status then + sleep = function(secs) + ztimer.sleep(secs * 1000) + end + end +end + +if not sleep then + sleep = function(secs) + os.execute("sleep " .. tonumber(secs)) + end +end +]] + +local thread = llthreads.new(include .. [[ + sleep(5) +]]) +thread:start() +local ok, err = thread:join(0) +print("thread:join(0): ", ok, err) +assert(ok == false) +assert(err == "timeout") + +print("thread:join(): ", thread:join()) +print("Done!") + diff --git a/test/test_register_llthreads.lua b/test/test_register_llthreads.lua new file mode 100644 index 0000000..f02bf86 --- /dev/null +++ b/test/test_register_llthreads.lua @@ -0,0 +1,12 @@ +local llthreads = require "llthreads" +local thread = llthreads.new([[ + if not package.preload.llthreads then + print("llthreads does not register in thread") + os.exit(-1) + end + local ok, err = pcall(require, "llthreads") + if not ok then + print("can not load llthreads: ", err) + os.exit(-2) + end +]]):start():join() -- cgit v1.2.3-55-g6feb