aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Melnichuk <alexeymelnichuck@gmail.com>2018-08-27 20:24:22 +0300
committerGitHub <noreply@github.com>2018-08-27 20:24:22 +0300
commit00ca97711b657c7d395d91212364a82dac1d4625 (patch)
tree07d166e87c2f294a0864501756e48d3c313309bb
parente33999a890c8bfdb0c1f753820e4261dabb67faa (diff)
parentcd91518d79388d5d42820a2b48918a7bf1e6d1a2 (diff)
downloadlua-llthreads2-00ca97711b657c7d395d91212364a82dac1d4625.tar.gz
lua-llthreads2-00ca97711b657c7d395d91212364a82dac1d4625.tar.bz2
lua-llthreads2-00ca97711b657c7d395d91212364a82dac1d4625.zip
Merge pull request #16 from osch/master
new method thread:interrupt()
-rw-r--r--.travis.yml1
-rw-r--r--appveyor.yml1
-rw-r--r--lakefile1
-rw-r--r--src/llthread.c37
-rw-r--r--src/lua/llthreads2/ex.lua9
-rw-r--r--test/test_interrupt.lua58
6 files changed, 107 insertions, 0 deletions
diff --git a/.travis.yml b/.travis.yml
index d629f05..19f6f5b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -57,6 +57,7 @@ script:
57 - lua test_threads_ex_opt_2.lua 57 - lua test_threads_ex_opt_2.lua
58 - lua test_threads_attr.lua 58 - lua test_threads_attr.lua
59 - lua test_integer.lua 59 - lua test_integer.lua
60 - lua test_interrupt.lua
60 # - lua test_register_llthreads.lua 61 # - lua test_register_llthreads.lua
61 62
62notifications: 63notifications:
diff --git a/appveyor.yml b/appveyor.yml
index db2206e..46a3235 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -72,6 +72,7 @@ test_script:
72 - lua test_threads_ex_opt_2.lua 72 - lua test_threads_ex_opt_2.lua
73 - lua test_threads_attr.lua 73 - lua test_threads_attr.lua
74 - lua test_integer.lua 74 - lua test_integer.lua
75 - lua test_interrupt.lua
75 # - lua test_register_llthreads.lua 76 # - lua test_register_llthreads.lua
76 77
77after_test: 78after_test:
diff --git a/lakefile b/lakefile
index fab4646..af9661e 100644
--- a/lakefile
+++ b/lakefile
@@ -44,6 +44,7 @@ target('test', install, function()
44 run_test('test_threads_ex_opt.lua') 44 run_test('test_threads_ex_opt.lua')
45 run_test('test_threads_ex_opt_2.lua') 45 run_test('test_threads_ex_opt_2.lua')
46 run_test('test_threads_attr.lua') 46 run_test('test_threads_attr.lua')
47 run_test('test_interrupt.lua')
47 48
48 49
49 if not test_summary() then 50 if not test_summary() then
diff --git a/src/llthread.c b/src/llthread.c
index 3155113..66efe7c 100644
--- a/src/llthread.c
+++ b/src/llthread.c
@@ -98,11 +98,17 @@ typedef pthread_t os_thread_t;
98 98
99#define LLTHREAD_OPEN_NAME LLTHREAD_OPEN_NAME_IMPL(LLTHREAD_MODULE_NAME) 99#define LLTHREAD_OPEN_NAME LLTHREAD_OPEN_NAME_IMPL(LLTHREAD_MODULE_NAME)
100 100
101#define LLTHREAD_STRINGIFY(x) #x
102#define LLTHREAD_TOSTRING(x) LLTHREAD_STRINGIFY(x)
103#define LLTHREAD_MODULE_NAME_STRING LLTHREAD_TOSTRING(LLTHREAD_MODULE_NAME)
104
105
101LLTHREADS_EXPORT_API int LLTHREAD_OPEN_NAME(lua_State *L); 106LLTHREADS_EXPORT_API int LLTHREAD_OPEN_NAME(lua_State *L);
102 107
103#define LLTHREAD_NAME "LLThread" 108#define LLTHREAD_NAME "LLThread"
104static const char *LLTHREAD_TAG = LLTHREAD_NAME; 109static const char *LLTHREAD_TAG = LLTHREAD_NAME;
105static const char *LLTHREAD_LOGGER_HOLDER = LLTHREAD_NAME " logger holder"; 110static const char *LLTHREAD_LOGGER_HOLDER = LLTHREAD_NAME " logger holder";
111static const char* LLTHREAD_INTERRUPTED_ERROR = LLTHREAD_MODULE_NAME_STRING ": thread was interrupted";
106 112
107typedef struct llthread_child_t { 113typedef struct llthread_child_t {
108 lua_State *L; 114 lua_State *L;
@@ -694,6 +700,32 @@ static int l_llthread_new(lua_State *L) {
694 return 1; 700 return 1;
695} 701}
696 702
703static void llthread_interrupt1(lua_State *L, lua_Debug *ar) {
704 (void)ar; /* unused arg. */
705 lua_sethook(L, NULL, 0, 0); /* reset hook */
706 luaL_error(L, LLTHREAD_INTERRUPTED_ERROR);
707}
708static void llthread_interrupt2(lua_State *L, lua_Debug *ar) {
709 (void)ar; /* unused arg. */
710 luaL_error(L, LLTHREAD_INTERRUPTED_ERROR);
711}
712
713static int l_llthread_interrupt(lua_State *L) {
714 llthread_t *this = l_llthread_at(L, 1);
715 llthread_child_t *child = this->child;
716 lua_Hook hook = llthread_interrupt1;
717 if (!lua_isnoneornil(L, 2))
718 hook = lua_toboolean(L, 2) ? llthread_interrupt2 : NULL;
719 if (child) {
720 if (hook)
721 lua_sethook(child->L, hook, LUA_MASKCALL|LUA_MASKRET|LUA_MASKCOUNT, 1);
722 else
723 lua_sethook(child->L, NULL, 0, 0); /* reset hook */
724 }
725 return 0;
726}
727
728
697static const struct luaL_Reg l_llthread_meth[] = { 729static const struct luaL_Reg l_llthread_meth[] = {
698 {"start", l_llthread_start }, 730 {"start", l_llthread_start },
699 {"join", l_llthread_join }, 731 {"join", l_llthread_join },
@@ -701,6 +733,7 @@ static const struct luaL_Reg l_llthread_meth[] = {
701 {"started", l_llthread_started }, 733 {"started", l_llthread_started },
702 {"detached", l_llthread_detached }, 734 {"detached", l_llthread_detached },
703 {"joinable", l_llthread_joinable }, 735 {"joinable", l_llthread_joinable },
736 {"interrupt", l_llthread_interrupt },
704 {"__gc", l_llthread_delete }, 737 {"__gc", l_llthread_delete },
705 738
706 {NULL, NULL} 739 {NULL, NULL}
@@ -769,5 +802,9 @@ LLTHREADS_EXPORT_API int LLTHREAD_OPEN_NAME(lua_State *L) {
769 l_llthread_push_version(L); 802 l_llthread_push_version(L);
770 lua_rawset(L, -3); 803 lua_rawset(L, -3);
771 804
805 lua_pushliteral(L, "interrupted_error");
806 lua_pushstring(L, LLTHREAD_INTERRUPTED_ERROR);
807 lua_rawset(L, -3);
808
772 return 1; 809 return 1;
773} 810}
diff --git a/src/lua/llthreads2/ex.lua b/src/lua/llthreads2/ex.lua
index f0c27d9..b943f5b 100644
--- a/src/lua/llthreads2/ex.lua
+++ b/src/lua/llthreads2/ex.lua
@@ -141,6 +141,15 @@ function thread_mt:joinable()
141 return self.thread:joinable() 141 return self.thread:joinable()
142end 142end
143 143
144--- Interrupt thread
145-- The thread is interrupted by installing a debug hook that
146-- creates an error.
147-- @tparam ?boolean if not given, interrupt only once,
148-- otherwise this arg sets or unsets permanent interrupt.
149function thread_mt:interrupt(arg)
150 return self.thread:interrupt(arg)
151end
152
144end 153end
145------------------------------------------------------------------------------- 154-------------------------------------------------------------------------------
146 155
diff --git a/test/test_interrupt.lua b/test/test_interrupt.lua
new file mode 100644
index 0000000..22c168e
--- /dev/null
+++ b/test/test_interrupt.lua
@@ -0,0 +1,58 @@
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
10do
11 local thread = llthreads.new(include .. [[
12 for i = 1, 10 do sleep(1) end
13 ]])
14
15 thread:start()
16 sleep(1)
17 thread:interrupt()
18
19 local ok, err = thread:join()
20 print("thread1:join(): ", ok, err)
21 assert(ok == false and err:match(llthreads.interrupted_error), "thread1 result")
22 print("--- Done interrupt1!")
23end
24
25
26do
27 local thread = llthreads.new(include .. [[
28 local ok, err = pcall(function() for i = 1, 10 do sleep(1) end end)
29 print("thread2:", ok, err)
30 assert(ok == false and err:match(llthreads.interrupted_error), "interrupt2 result")
31 ]])
32
33 thread:start()
34 sleep(1)
35 thread:interrupt()
36
37 local ok, err = thread:join()
38 print("thread2:join(): ", ok, err)
39 assert(ok, "thread2 result")
40 print("--- Done interrupt2!")
41end
42
43do
44 local thread = llthreads.new(include .. [[
45 local ok, err = pcall(function() for i = 1, 10 do sleep(1) end end)
46 print("thread3:", ok, err)
47 ]])
48
49 thread:start()
50 sleep(1)
51 thread:interrupt(true)
52
53 local ok, err = thread:join()
54 print("thread3:join(): ", ok, err)
55 assert(ok == false and err:match(llthreads.interrupted_error), "thread3 result")
56 print("--- Done interrupt3!")
57end
58