From 84294d0b5462d0a05fb5d53df5a64f7ee624a726 Mon Sep 17 00:00:00 2001
From: Benoit Germain
- timeout is an optional number >= 0 (the default if unspecified).
-
-stack_tbl is a table describing where the error was thrown.
-
- If you use :join(), make sure your lane main function returns a non-nil value so you can tell timeout and error cases apart from succesful return (using the .status property may be risky, since it might change between a timed out join and the moment you read it).
+ timeout is an optional number >= 0 (the default if unspecified).
- Waits until the lane finishes, or timeout seconds have passed.
-
- Returns nil, "timeout" on timeout, nil,err,stack_tbl if the lane hit an error, nil, "killed" if forcefully killed, or the return values of the lane.
-
- Unlike in reading the results in table fashion, errors are not propagated.
-
- In "extended" mode, stack_tbl is an array of tables containing info gathered with lua_getinfo() ("source","currentline","name","namewhat","what").
-
- In "basic" mode, stack_tbl is an array of "<filename>:<line>" strings. Use table.concat() to format it to your liking (or just ignore it).
-
+ Waits until the lane finishes, or timeout seconds have passed.
+ Unlike in reading the results in table fashion, errors are not propagated.
+ Possible return values are:
+
+
+
+
+
diff --git a/src/lane.cpp b/src/lane.cpp index 3bb98b9..eaf1c1e 100644 --- a/src/lane.cpp +++ b/src/lane.cpp @@ -135,7 +135,11 @@ static LUAG_FUNC(thread_join) switch (_lane->status) { case Lane::Done: { + bool const _calledFromIndex{ lua_toboolean(L_, lua_upvalueindex(1)) ? true : false }; // this upvalue doesn't exist when called from Lua int const _n{ lua_gettop(_L2) }; // whole L2 stack + if (!_calledFromIndex && (_n == 0 || lua_isnil(_L2, 1))) { + raise_luaL_error(L_, "First return value must be non-nil when using join()"); + } if ( (_n > 0) && (InterCopyContext{ _lane->U, DestState{ L_ }, SourceState{ _L2 }, {}, {}, {}, {}, {} }.inter_move(_n) != InterCopyResult::Success) @@ -161,7 +165,11 @@ static LUAG_FUNC(thread_join) break; case Lane::Cancelled: - _ret = 0; + // we should have a single value, kCancelError, in the stack of _L2 + LUA_ASSERT(L_, lua_gettop(_L2) == 1 && kCancelError.equals(_L2, 1)); + lua_pushnil(L_); // L_: lane nil + kCancelError.pushKey(L_); // L_: lane nil cancel_error + _ret = 2; break; default: @@ -207,8 +215,10 @@ static int thread_index_number(lua_State* L_) lua_pushinteger(L_, 0); // L_: lane n {uv} 0 lua_pushboolean(L_, 1); // L_: lane n {uv} 0 true lua_rawset(L_, kUsr); // L_: lane n {uv} + // tell join() that we are called from __index, to avoid raising an error if the first returned value is not nil + lua_pushboolean(L_, 1); // L_: lane n {uv} true // wait until thread has completed, transfer everything from the lane's stack to our side - lua_pushcfunction(L_, LG_thread_join); // L_: lane n {uv} join + lua_pushcclosure(L_, LG_thread_join, 1); // L_: lane n {uv} join lua_pushvalue(L_, kSelf); // L_: lane n {uv} join lane lua_call(L_, 1, LUA_MULTRET); // lane:join() // L_: lane n {uv} ... switch (_lane->status) { diff --git a/tests/cancel.lua b/tests/cancel.lua index 92ab439..42ae839 100644 --- a/tests/cancel.lua +++ b/tests/cancel.lua @@ -15,6 +15,7 @@ local SLEEP = function(...) local lanes = require "lanes" local k, v = lanes.sleep(...) assert(k == nil and v == "timeout") + return true end local sleeper = lanes.gen("*", sleeperBody)(...) -- then wait for the lane to terminate diff --git a/tests/cyclic.lua b/tests/cyclic.lua index 656fde3..553d2a9 100644 --- a/tests/cyclic.lua +++ b/tests/cyclic.lua @@ -30,6 +30,7 @@ local function lane1() WR( "Via upvalue: ", same(a,b[1]), same(a[1],b) ) assert( a[1]==b ) assert( b[1]==a ) + return true end local L1= lanes.gen( "io", lane1 )() -- ...running @@ -40,6 +41,7 @@ local function lane2( aa, bb ) WR( "Via parameters:", same(aa,bb[1]), same(aa[1],bb) ) assert( aa[1]==bb ) assert( bb[1]==aa ) + return true end local L2= lanes.gen( "io", lane2 )( a, b ) -- ...running @@ -52,6 +54,7 @@ c.a= c local function lane3( cc ) WR( "Directly recursive: ", same(cc, cc.a) ) assert( cc and cc.a==cc ) + return true end local L3= lanes.gen("io", lane3)(c) diff --git a/tests/fifo.lua b/tests/fifo.lua index d741931..e1bfeae 100644 --- a/tests/fifo.lua +++ b/tests/fifo.lua @@ -82,4 +82,6 @@ print( B:receive( 2.0)) -- by multiple threads (other parts will be copied but the 'linda' -- handle is shared userdata and will thus point to the single place) lanes.timer_lane:cancel() -- hard cancel, 0 timeout -lanes.timer_lane:join() \ No newline at end of file +local status, err = lanes.timer_lane:join() +assert(status == nil and err == lanes.cancel_error, "status="..tostring(status).." err="..tostring(err)) +print "TEST OK" diff --git a/tests/finalizer.lua b/tests/finalizer.lua index 2acc39d..3158c65 100644 --- a/tests/finalizer.lua +++ b/tests/finalizer.lua @@ -39,6 +39,7 @@ local function lane(error_) error(error_, 0) -- exception here; the value needs NOT be a string end -- no exception + return true end -- diff --git a/tests/keeper.lua b/tests/keeper.lua index 0220eba..2f731f0 100644 --- a/tests/keeper.lua +++ b/tests/keeper.lua @@ -155,6 +155,7 @@ if true then c.some= 3 assert( c.some==3 ) PRINT("c.some == " .. c.some) + return true end PRINT("lane started") diff --git a/tests/linda_perf.lua b/tests/linda_perf.lua index 0b25989..4b0c005 100644 --- a/tests/linda_perf.lua +++ b/tests/linda_perf.lua @@ -56,6 +56,7 @@ local eater = function( l, loop) -- print "loop is over" key, val = l:receive( "done") print("eater: done ("..val..")") + return true end -- ################################################################################################# @@ -73,6 +74,7 @@ local gobbler = function( l, loop, batch) print "loop is over" key, val = l:receive( "done") print("gobbler: done ("..val..")") + return true end -- ################################################################################################# diff --git a/tests/parallel_os_calls.lua b/tests/parallel_os_calls.lua index 596053c..7e7de26 100644 --- a/tests/parallel_os_calls.lua +++ b/tests/parallel_os_calls.lua @@ -1,10 +1,10 @@ local lanes = require "lanes".configure() print( os.date()) local linda = lanes.linda() -local l1 = lanes.gen("os,base", function() print "start sleeping" linda:receive(10, "null") print("finished_sleeping " .. os.date()) end)() -lanes.gen("os,base", function() print "start sleeping" linda:receive(9, "null") print("finished_sleeping " .. os.date()) end)() -lanes.gen("os,base", function() print "start sleeping" linda:receive(9, "null") print("finished_sleeping " .. os.date()) end)() -lanes.gen("os,base", function() print "start sleeping" linda:receive(9, "null") print("finished_sleeping " .. os.date()) end)() +local l1 = lanes.gen("os,base", function() print "start sleeping" linda:receive(3, "null") print("finished_sleeping " .. os.date()) return true end)() +lanes.gen("os,base", function() print "start sleeping" linda:receive(2, "null") print("finished_sleeping " .. os.date()) end)() +lanes.gen("os,base", function() print "start sleeping" linda:receive(2, "null") print("finished_sleeping " .. os.date()) end)() +lanes.gen("os,base", function() print "start sleeping" linda:receive(2, "null") print("finished_sleeping " .. os.date()) end)() -- wait, else all lanes will get hard-cancelled at stat shutdown l1:join() --[[ diff --git a/tests/pingpong.lua b/tests/pingpong.lua index 30cd360..fdc60a6 100644 --- a/tests/pingpong.lua +++ b/tests/pingpong.lua @@ -21,6 +21,7 @@ local pingpong = function(name, qr, qs, start) q:send(qs, val) count = count + 1 end + return true end -- pingpong("L1", '0', '1', true) @@ -28,4 +29,5 @@ local t1, err1 = lanes.gen("*", pingpong)("L1", 'a', 'b', true) local t2, err2 = lanes.gen("*", pingpong)("L2", 'b', 'a', false) t1:join() -t2:join() \ No newline at end of file +t2:join() +print "TEST OK" diff --git a/tests/rupval.lua b/tests/rupval.lua index 1079168..122e0ac 100644 --- a/tests/rupval.lua +++ b/tests/rupval.lua @@ -25,6 +25,19 @@ end local g = lanes.gen( "base", a) -local l = g(10) +local l = g(7) local r = l:join() +assert(r == y) print(r) + +local l = g(8) +local r = l:join() +assert(r == z) +print(r) + +local l = g(9) +local r = l:join() +assert(r == x) +print(r) + +print "TEST OK" -- cgit v1.2.3-55-g6feb |