aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/index.html1
-rw-r--r--src/lane.cpp31
-rw-r--r--tests/func_is_string.lua31
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
737static 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_) 765static 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_)
859namespace { 877namespace {
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 @@
1local lanes = require "lanes" 1local lanes = require "lanes"
2lanes.configure() 2
3-- Lua 5.4 specific:
4if _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)
19end
20
3 21
4local options = {globals = { b = 666 }} 22local options = {globals = { b = 666 }}
5 23
6-- local gen1 = lanes.gen("*", "dofile('fibonacci.lua')") 24local gen1 = lanes.gen("*", "return true, dofile('fibonacci.lua')")
7local gen2 = lanes.gen(options, "return b") 25local gen2 = lanes.gen(options, "return b")
8 26
9-- fibLane = gen1() 27fibLane = gen1()
28lanes.sleep(0.1)
29print(fibLane, fibLane.status)
30local _status, _err = fibLane:join()
31print(_status, _err)
32
10retLane1, retLane2 = gen2(), gen2() 33retLane1, retLane2 = gen2(), gen2()
11-- fibLane:join()
12 34
13print( retLane1[1], retLane2[1]) 35print( retLane1[1], retLane2[1])
36print "TEST OK" \ No newline at end of file