diff options
-rw-r--r-- | docs/index.html | 1 | ||||
-rw-r--r-- | src/lane.cpp | 31 | ||||
-rw-r--r-- | tests/func_is_string.lua | 31 |
3 files changed, 54 insertions, 9 deletions
diff --git a/docs/index.html b/docs/index.html index 400ceb1..73753d7 100644 --- a/docs/index.html +++ b/docs/index.html | |||
@@ -1008,6 +1008,7 @@ | |||
1008 | <li><tt>nil, "killed"</tt> if forcefully killed.</li> | 1008 | <li><tt>nil, "killed"</tt> if forcefully killed.</li> |
1009 | <li>The return values of the lane function. If the first return value is <tt>nil</tt> (or there is no return value), an error is raised, to make sure you can tell timeout and error cases apart from successful return.</li> | 1009 | <li>The return values of the lane function. If the first return value is <tt>nil</tt> (or there is no return value), an error is raised, to make sure you can tell timeout and error cases apart from successful return.</li> |
1010 | </ul> | 1010 | </ul> |
1011 | If the lane handle obtained from <tt>lanes.gen()</tt> is to-be-closed, closing the value will cause a call to <tt>join()</tt>. Since it is implicit, the lane body isn't forced to return non-<tt>nil</tt> in that case. | ||
1011 | </p> | 1012 | </p> |
1012 | 1013 | ||
1013 | <table border=1 bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1014 | <table border=1 bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
diff --git a/src/lane.cpp b/src/lane.cpp index eaf1c1e..1a01a24 100644 --- a/src/lane.cpp +++ b/src/lane.cpp | |||
@@ -135,9 +135,9 @@ static LUAG_FUNC(thread_join) | |||
135 | switch (_lane->status) { | 135 | switch (_lane->status) { |
136 | case Lane::Done: | 136 | case Lane::Done: |
137 | { | 137 | { |
138 | bool const _calledFromIndex{ lua_toboolean(L_, lua_upvalueindex(1)) ? true : false }; // this upvalue doesn't exist when called from Lua | 138 | bool const _calledFromLua{ lua_toboolean(L_, lua_upvalueindex(1)) ? false : true }; // this upvalue doesn't exist when called from Lua |
139 | int const _n{ lua_gettop(_L2) }; // whole L2 stack | 139 | int const _n{ lua_gettop(_L2) }; // whole L2 stack |
140 | if (!_calledFromIndex && (_n == 0 || lua_isnil(_L2, 1))) { | 140 | if (_calledFromLua && (_n == 0 || lua_isnil(_L2, 1))) { |
141 | raise_luaL_error(L_, "First return value must be non-nil when using join()"); | 141 | raise_luaL_error(L_, "First return value must be non-nil when using join()"); |
142 | } | 142 | } |
143 | if ( | 143 | if ( |
@@ -216,7 +216,7 @@ static int thread_index_number(lua_State* L_) | |||
216 | lua_pushboolean(L_, 1); // L_: lane n {uv} 0 true | 216 | lua_pushboolean(L_, 1); // L_: lane n {uv} 0 true |
217 | lua_rawset(L_, kUsr); // L_: lane n {uv} | 217 | lua_rawset(L_, kUsr); // L_: lane n {uv} |
218 | // tell join() that we are called from __index, to avoid raising an error if the first returned value is not nil | 218 | // tell join() that we are called from __index, to avoid raising an error if the first returned value is not nil |
219 | lua_pushboolean(L_, 1); // L_: lane n {uv} true | 219 | std::ignore = luaG_pushstring(L_, "[]"); // L_: lane n {uv} "[]" |
220 | // wait until thread has completed, transfer everything from the lane's stack to our side | 220 | // wait until thread has completed, transfer everything from the lane's stack to our side |
221 | lua_pushcclosure(L_, LG_thread_join, 1); // L_: lane n {uv} join | 221 | lua_pushcclosure(L_, LG_thread_join, 1); // L_: lane n {uv} join |
222 | lua_pushvalue(L_, kSelf); // L_: lane n {uv} join lane | 222 | lua_pushvalue(L_, kSelf); // L_: lane n {uv} join lane |
@@ -733,6 +733,24 @@ static void lane_main(Lane* lane_) | |||
733 | 733 | ||
734 | // ################################################################################################# | 734 | // ################################################################################################# |
735 | 735 | ||
736 | #if LUA_VERSION_NUM >= 504 | ||
737 | static LUAG_FUNC(lane_close) | ||
738 | { | ||
739 | [[maybe_unused]] Lane* const _lane{ ToLane(L_, 1) }; // L_: lane err|nil | ||
740 | // drop the error if any | ||
741 | lua_settop(L_, 1); // L_: lane | ||
742 | |||
743 | // no error if the lane body doesn't return a non-nil first value | ||
744 | std::ignore = luaG_pushstring(L_, "close"); // L_: lane "close" | ||
745 | lua_pushcclosure(L_, LG_thread_join, 1); // L_: lane join() | ||
746 | lua_insert(L_, 1); // L_: join() lane | ||
747 | lua_call(L_, 1, LUA_MULTRET); // L_: join() results | ||
748 | return lua_gettop(L_); | ||
749 | } | ||
750 | #endif // LUA_VERSION_NUM >= 504 | ||
751 | |||
752 | // ################################################################################################# | ||
753 | |||
736 | // = thread_gc( lane_ud ) | 754 | // = thread_gc( lane_ud ) |
737 | // | 755 | // |
738 | // Cleanup for a thread userdata. If the thread is still executing, leave it | 756 | // Cleanup for a thread userdata. If the thread is still executing, leave it |
@@ -744,7 +762,7 @@ static void lane_main(Lane* lane_) | |||
744 | // and the issue of canceling/killing threads at gc is not very nice, either | 762 | // and the issue of canceling/killing threads at gc is not very nice, either |
745 | // (would easily cause waits at gc cycle, which we don't want). | 763 | // (would easily cause waits at gc cycle, which we don't want). |
746 | // | 764 | // |
747 | [[nodiscard]] static int lane_gc(lua_State* L_) | 765 | static LUAG_FUNC(lane_gc) |
748 | { | 766 | { |
749 | bool _have_gc_cb{ false }; | 767 | bool _have_gc_cb{ false }; |
750 | Lane* const _lane{ ToLane(L_, 1) }; // L_: ud | 768 | Lane* const _lane{ ToLane(L_, 1) }; // L_: ud |
@@ -859,7 +877,10 @@ void Lane::changeDebugName(int const nameIdx_) | |||
859 | namespace { | 877 | namespace { |
860 | namespace local { | 878 | namespace local { |
861 | static struct luaL_Reg const sLaneFunctions[] = { | 879 | static struct luaL_Reg const sLaneFunctions[] = { |
862 | { "__gc", lane_gc }, | 880 | #if LUA_VERSION_NUM >= 504 |
881 | { "__close", LG_lane_close }, | ||
882 | #endif // LUA_VERSION_NUM >= 504 | ||
883 | { "__gc", LG_lane_gc }, | ||
863 | { "__index", LG_thread_index }, | 884 | { "__index", LG_thread_index }, |
864 | { "cancel", LG_thread_cancel }, | 885 | { "cancel", LG_thread_cancel }, |
865 | { "get_debug_threadname", LG_get_debug_threadname }, | 886 | { "get_debug_threadname", LG_get_debug_threadname }, |
diff --git a/tests/func_is_string.lua b/tests/func_is_string.lua index d7cf0b2..a14c460 100644 --- a/tests/func_is_string.lua +++ b/tests/func_is_string.lua | |||
@@ -1,13 +1,36 @@ | |||
1 | local lanes = require "lanes" | 1 | local lanes = require "lanes" |
2 | lanes.configure() | 2 | |
3 | -- Lua 5.4 specific: | ||
4 | if _VERSION >= "Lua 5.4" then | ||
5 | -- go through a string so that the script we are in doesn't trigger a parse error with older Lua | ||
6 | local res = assert(load [[ | ||
7 | local lanes = require 'lanes' | ||
8 | local r | ||
9 | do | ||
10 | local h <close> = lanes.gen('*', lanes.sleep)(0.5) | ||
11 | r = h | ||
12 | end -- h is closed here | ||
13 | return r.status | ||
14 | ]])() | ||
15 | -- when the do...end block is exited, the to-be-closed variable h is closed, which internally calls h:join() | ||
16 | -- therefore the status of the lane should be "done" | ||
17 | assert(res == "done") | ||
18 | print("close result:", res) | ||
19 | end | ||
20 | |||
3 | 21 | ||
4 | local options = {globals = { b = 666 }} | 22 | local options = {globals = { b = 666 }} |
5 | 23 | ||
6 | -- local gen1 = lanes.gen("*", "dofile('fibonacci.lua')") | 24 | local gen1 = lanes.gen("*", "return true, dofile('fibonacci.lua')") |
7 | local gen2 = lanes.gen(options, "return b") | 25 | local gen2 = lanes.gen(options, "return b") |
8 | 26 | ||
9 | -- fibLane = gen1() | 27 | fibLane = gen1() |
28 | lanes.sleep(0.1) | ||
29 | print(fibLane, fibLane.status) | ||
30 | local _status, _err = fibLane:join() | ||
31 | print(_status, _err) | ||
32 | |||
10 | retLane1, retLane2 = gen2(), gen2() | 33 | retLane1, retLane2 = gen2(), gen2() |
11 | -- fibLane:join() | ||
12 | 34 | ||
13 | print( retLane1[1], retLane2[1]) | 35 | print( retLane1[1], retLane2[1]) |
36 | print "TEST OK" \ No newline at end of file | ||