aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Melnichuk <mimir@newmail.ru>2014-02-04 11:06:17 +0400
committerAlexey Melnichuk <mimir@newmail.ru>2014-02-04 11:06:17 +0400
commitcef9a7a112a8322e2c6498021df59e4a8f7b5246 (patch)
tree5a885427afef52cbd3067c79b1f24406e42ecf87
parentd35bf824e0dd9c3584d1587b5ec662a0fcf71bfe (diff)
downloadlua-llthreads2-cef9a7a112a8322e2c6498021df59e4a8f7b5246.tar.gz
lua-llthreads2-cef9a7a112a8322e2c6498021df59e4a8f7b5246.tar.bz2
lua-llthreads2-cef9a7a112a8322e2c6498021df59e4a8f7b5246.zip
Add. `thread:alive()` method.
-rw-r--r--.travis.yml1
-rw-r--r--README.md18
-rw-r--r--lakefile1
-rw-r--r--src/llthread.c69
-rw-r--r--test/test_alive.lua35
5 files changed, 124 insertions, 0 deletions
diff --git a/.travis.yml b/.travis.yml
index b6dc082..dc2ef16 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -56,6 +56,7 @@ script:
56 - lua$LUA_SFX test_logger.lua 56 - lua$LUA_SFX test_logger.lua
57 - lua$LUA_SFX test_pass_cfunction.lua 57 - lua$LUA_SFX test_pass_cfunction.lua
58 - lua$LUA_SFX test_load_llthreads2.lua 58 - lua$LUA_SFX test_load_llthreads2.lua
59 - lua$LUA_SFX test_alive.lua
59 60
60notifications: 61notifications:
61 email: 62 email:
diff --git a/README.md b/README.md
index ba38ebd..66e4d8b 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,7 @@ This is full dropin replacement for [llthreads](https://github.com/Neopallium/lu
13##Additional 13##Additional
14* thread:join() method support zero timeout to check if thread alive (does not work on Windows with pthreads) 14* thread:join() method support zero timeout to check if thread alive (does not work on Windows with pthreads)
15* thread:join() method support arbitrary timeout on Windows threads 15* thread:join() method support arbitrary timeout on Windows threads
16* thread:alive() method return whether the thread is alive (does not work on Windows with pthreads)
16* set_logger function allow logging errors (crash Lua VM) in current llthread's threads 17* set_logger function allow logging errors (crash Lua VM) in current llthread's threads
17* thread:start() has additional parameter which control in which thread child Lua VM will be destroyed 18* thread:start() has additional parameter which control in which thread child Lua VM will be destroyed
18* allow pass cfunctions to child thread (e.g. to initialize Lua state) 19* allow pass cfunctions to child thread (e.g. to initialize Lua state)
@@ -89,5 +90,22 @@ llthreads.new([[
89]], preload):start(true) 90]], preload):start(true)
90``` 91```
91 92
93### Wait while thread is alive
94``` Lua
95local thread = require "llthreads".new[[
96 require "utils".sleep(5)
97 return 1
98]]
99thread:start()
100
101-- we can not use `thread:join(0)` because we can not call it twice
102-- so all returned vaules will be lost
103while thread:alive() do
104 -- do some work
105end
106
107local ok, ret = thread:join() -- true, 1
108```
109
92[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/moteus/lua-llthreads2/trend.png)](https://bitdeli.com/free "Bitdeli Badge") 110[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/moteus/lua-llthreads2/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
93 111
diff --git a/lakefile b/lakefile
index b7786b1..060035a 100644
--- a/lakefile
+++ b/lakefile
@@ -36,6 +36,7 @@ target('test', install, function()
36 run_test('test_register_ffi.lua') 36 run_test('test_register_ffi.lua')
37 run_test('test_logger.lua') 37 run_test('test_logger.lua')
38 run_test('test_pass_cfunction.lua') 38 run_test('test_pass_cfunction.lua')
39 run_test('test_alive.lua')
39 40
40 if not test_summary() then 41 if not test_summary() then
41 quit("test fail") 42 quit("test fail")
diff --git a/src/llthread.c b/src/llthread.c
index ac485e3..0ffa727 100644
--- a/src/llthread.c
+++ b/src/llthread.c
@@ -457,6 +457,35 @@ static int llthread_join(llthread_t *this, join_timeout_t timeout) {
457 } 457 }
458} 458}
459 459
460static int llthread_alive(llthread_t *this) {
461 llthread_validate(this);
462
463 if(IS(this, JOINED)){
464 return JOIN_OK;
465 } else{
466#ifndef USE_PTHREAD
467 DWORD ret = 0;
468 if(INVALID_THREAD == this->thread) return JOIN_OK;
469 ret = WaitForSingleObject( this->thread, 0 );
470 if( ret == WAIT_OBJECT_0) return JOIN_OK;
471 if( ret == WAIT_TIMEOUT ) return JOIN_ETIMEDOUT;
472 return JOIN_FAIL;
473#else
474 int rc = pthread_kill(this->thread, 0);
475 if(rc == 0){ /* still alive */
476 return JOIN_ETIMEDOUT;
477 }
478
479 if(rc != ESRCH){
480 /*@fixme what else it can be ?*/
481 return rc;
482 }
483
484 return JOIN_OK;
485#endif
486 }
487}
488
460static llthread_t *llthread_create(lua_State *L, const char *code, size_t code_len) { 489static llthread_t *llthread_create(lua_State *L, const char *code, size_t code_len) {
461 llthread_t *this = llthread_new(); 490 llthread_t *this = llthread_new();
462 llthread_child_t *child = this->child; 491 llthread_child_t *child = this->child;
@@ -592,6 +621,45 @@ static int l_llthread_join(lua_State *L) {
592 621
593} 622}
594 623
624static int l_llthread_alive(lua_State *L) {
625 llthread_t *this = l_llthread_at(L, 1);
626 llthread_child_t *child = this->child;
627 int rc;
628
629 if(!IS(this, STARTED )) {
630 return fail(L, "Can't join a thread that hasn't be started.");
631 }
632 if( IS(this, DETACHED) && !IS(this, JOINABLE)) {
633 return fail(L, "Can't join a thread that has been detached.");
634 }
635 if( IS(this, JOINED )) {
636 return fail(L, "Can't join a thread that has already been joined.");
637 }
638
639 /* join the thread. */
640 rc = llthread_alive(this);
641
642 if( rc == JOIN_ETIMEDOUT ){
643 lua_pushboolean(L, 1);
644 return 1;
645 }
646
647 if(rc == JOIN_OK){
648 lua_pushboolean(L, 0);
649 return 1;
650 }
651
652 {
653 char buf[ERROR_LEN];
654 strerror_r(errno, buf, ERROR_LEN);
655
656 /* llthread_cleanup_child(this); */
657
658 return fail(L, buf);
659 }
660
661}
662
595static int l_llthread_new(lua_State *L) { 663static int l_llthread_new(lua_State *L) {
596 size_t lua_code_len; const char *lua_code = luaL_checklstring(L, 1, &lua_code_len); 664 size_t lua_code_len; const char *lua_code = luaL_checklstring(L, 1, &lua_code_len);
597 llthread_t **this = lutil_newudatap(L, llthread_t*, LLTHREAD_TAG); 665 llthread_t **this = lutil_newudatap(L, llthread_t*, LLTHREAD_TAG);
@@ -605,6 +673,7 @@ static int l_llthread_new(lua_State *L) {
605static const struct luaL_Reg l_llthread_meth[] = { 673static const struct luaL_Reg l_llthread_meth[] = {
606 {"start", l_llthread_start }, 674 {"start", l_llthread_start },
607 {"join", l_llthread_join }, 675 {"join", l_llthread_join },
676 {"alive", l_llthread_alive },
608 {"__gc", l_llthread_delete }, 677 {"__gc", l_llthread_delete },
609 678
610 {NULL, NULL} 679 {NULL, NULL}
diff --git a/test/test_alive.lua b/test/test_alive.lua
new file mode 100644
index 0000000..ecce163
--- /dev/null
+++ b/test/test_alive.lua
@@ -0,0 +1,35 @@
1local llthreads = require"llthreads"
2local utils = require "utils"
3local sleep = utils.sleep
4
5local include = utils.thread_init .. [[
6local llthreads = require"llthreads"
7local sleep = require "utils".sleep
8]]
9
10local thread = llthreads.new(include .. [[
11 sleep(5)
12 return 1,2,3
13]])
14
15assert(nil == thread:alive())
16
17thread:start()
18
19assert(true == thread:alive())
20
21for i = 1, 10 do
22 if not thread:alive() then break end
23 sleep(1)
24end
25
26assert(false == thread:alive())
27
28local ok,a,b,c = thread:join(0)
29assert(ok == true)
30assert(a == 1)
31assert(b == 2)
32assert(c == 3)
33
34print("Done!")
35