aboutsummaryrefslogtreecommitdiff
path: root/unit_tests/scripts/lane
diff options
context:
space:
mode:
Diffstat (limited to 'unit_tests/scripts/lane')
-rw-r--r--unit_tests/scripts/lane/body_is_a_c_function.lua28
-rw-r--r--unit_tests/scripts/lane/cooperative_shutdown.lua16
-rw-r--r--unit_tests/scripts/lane/tasking_cancelling.lua112
-rw-r--r--unit_tests/scripts/lane/tasking_cancelling_with_hook.lua68
-rw-r--r--unit_tests/scripts/lane/tasking_comms_criss_cross.lua2
-rw-r--r--unit_tests/scripts/lane/tasking_communications.lua4
-rw-r--r--unit_tests/scripts/lane/tasking_join_test.lua16
-rw-r--r--unit_tests/scripts/lane/tasking_send_receive_code.lua20
-rw-r--r--unit_tests/scripts/lane/uncooperative_shutdown.lua2
9 files changed, 177 insertions, 91 deletions
diff --git a/unit_tests/scripts/lane/body_is_a_c_function.lua b/unit_tests/scripts/lane/body_is_a_c_function.lua
new file mode 100644
index 0000000..d8d329f
--- /dev/null
+++ b/unit_tests/scripts/lane/body_is_a_c_function.lua
@@ -0,0 +1,28 @@
1local lanes = require "lanes".configure()
2
3-- ##################################################################################################
4-- ##################################################################################################
5-- ##################################################################################################
6
7-- we can create a generator where the lane body is a C function
8do
9 local b, g = pcall(lanes.gen, "*", print)
10 assert(b == true and type(g) == "function")
11 -- we can start the lane
12 local b, h = pcall(g, "hello")
13 -- the lane runs normally
14 h:join()
15 assert(h.status == "done")
16end
17
18-- we can create a generator where the lane body is a C function that raises an error
19do
20 local b, g = pcall(lanes.gen, "*", error)
21 assert(b == true and type(g) == "function")
22 -- we can start the lane
23 local b, h = pcall(g, "this is an error")
24 -- this provides the error that occurred in the lane
25 local s, e, t = h:join()
26 assert(h.status == "error")
27 assert(s == nil and e == "this is an error" and t == nil)
28end
diff --git a/unit_tests/scripts/lane/cooperative_shutdown.lua b/unit_tests/scripts/lane/cooperative_shutdown.lua
index 756e33c..0a0943e 100644
--- a/unit_tests/scripts/lane/cooperative_shutdown.lua
+++ b/unit_tests/scripts/lane/cooperative_shutdown.lua
@@ -1,10 +1,10 @@
1local lanes = require "lanes" 1local lanes = require "lanes".configure{on_state_create = require "fixture".on_state_create}
2 2
3-- launch lanes that cooperate properly with cancellation request 3-- launch lanes that cooperate properly with cancellation request
4 4
5local lane1 = function() 5local lane1 = function()
6 lane_threadname("lane1") 6 lane_threadname("lane1")
7 -- loop breaks on cancellation request 7 -- loop breaks on soft cancellation request
8 repeat 8 repeat
9 lanes.sleep(0) 9 lanes.sleep(0)
10 until cancel_test() 10 until cancel_test()
@@ -23,7 +23,6 @@ end
23local lane3 = function() 23local lane3 = function()
24 lane_threadname("lane3") 24 lane_threadname("lane3")
25 -- this one cooperates too, because of the hook cancellation modes that Lanes will be using 25 -- this one cooperates too, because of the hook cancellation modes that Lanes will be using
26 -- but not with LuaJIT, because the function is compiled, and we don't call anyone, so no hook triggers
27 local fixture = require "fixture" 26 local fixture = require "fixture"
28 repeat until fixture.give_me_back(false) 27 repeat until fixture.give_me_back(false)
29end 28end
@@ -43,7 +42,14 @@ local h2 = g2(linda)
43 42
44local h3 = g3() 43local h3 = g3()
45 44
46-- wait until they are both started 45lanes.sleep(0.1)
47repeat until h1.status == "running" and h2.status == "waiting" and h3.status == "running" 46
47local is_running = function(lane_h)
48 local status = lane_h.status
49 return status == "running" or status == "waiting"
50end
51
52-- wait until they are all started
53repeat until is_running(h1) and is_running(h2) and is_running(h3)
48 54
49-- let the script terminate, Lanes should not crash at shutdown 55-- let the script terminate, Lanes should not crash at shutdown
diff --git a/unit_tests/scripts/lane/tasking_cancelling.lua b/unit_tests/scripts/lane/tasking_cancelling.lua
index 85600ab..d153ffa 100644
--- a/unit_tests/scripts/lane/tasking_cancelling.lua
+++ b/unit_tests/scripts/lane/tasking_cancelling.lua
@@ -1,4 +1,7 @@
1local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure(config).configure() 1local require_fixture_result_1, require_fixture_result_2 = require "fixture"
2local fixture = assert(require_fixture_result_1)
3
4local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure{on_state_create = fixture.on_state_create}.configure()
2print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2) 5print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2)
3local lanes = require_lanes_result_1 6local lanes = require_lanes_result_1
4 7
@@ -15,69 +18,34 @@ local lanes_linda = assert(lanes.linda)
15-- ################################################################################################## 18-- ##################################################################################################
16-- ################################################################################################## 19-- ##################################################################################################
17 20
18local function task(a, b, c) 21-- cancellation of cooperating lanes
19 lane_threadname("task("..a..","..b..","..c..")") 22local cooperative = function()
20 --error "111" -- testing error messages 23 local fixture = assert(require "fixture")
21 assert(hey) 24 local which_cancel
22 local v=0 25 repeat
23 for i=a,b,c do 26 fixture.block_for(0.2)
24 v= v+i 27 which_cancel = cancel_test()
25 end 28 until which_cancel
26 return v, hey 29 return which_cancel
27end
28
29local gc_cb = function(name_, status_)
30 PRINT(" ---> lane '" .. name_ .. "' collected with status '" .. status_ .. "'")
31end 30end
31-- soft and hard are behaviorally equivalent when no blocking linda operation is involved
32local cooperative_lane_soft = lanes_gen("*", { name = 'auto' }, cooperative)()
33local a, b = cooperative_lane_soft:cancel("soft", 0) -- issue request, do not wait for lane to terminate
34assert(a == false and b == "timeout", "got " .. tostring(a) .. " " .. tostring(b))
35assert(cooperative_lane_soft[1] == "soft") -- return value of the lane body is the value returned by cancel_test()
36local cooperative_lane_hard = lanes_gen("*", { name = 'auto' }, cooperative)()
37local c, d = cooperative_lane_hard:cancel("hard", 0) -- issue request, do not wait for lane to terminate
38assert(a == false and b == "timeout", "got " .. tostring(c) .. " " .. tostring(d))
39assert(cooperative_lane_hard[1] == "hard") -- return value of the lane body is the value returned by cancel_test()
32 40
33-- ################################################################################################## 41-- ##################################################################################################
34-- ##################################################################################################
35-- ##################################################################################################
36
37PRINT("\n\n", "---=== Tasking (cancelling) ===---", "\n\n")
38
39local task_launch2 = lanes_gen("", { name = 'auto', globals={hey=true}, gc_cb = gc_cb }, task)
40
41local N=999999999
42local lane9= task_launch2(1,N,1) -- huuuuuuge...
43
44-- Wait until state changes "pending"->"running"
45--
46local st
47local t0= os.time()
48while os.time()-t0 < 5 do
49 st= lane9.status
50 io.stderr:write((i==1) and st.." " or '.')
51 if st~="pending" then break end
52end
53PRINT(" "..st)
54
55if st=="error" then
56 local _= lane9[0] -- propagate the error here
57end
58if st=="done" then
59 error("Looping to "..N.." was not long enough (cannot test cancellation)")
60end
61assert(st=="running", "st == " .. st)
62
63-- when running under luajit, the function is JIT-ed, and the instruction count isn't hit, so we need a different hook
64lane9:cancel(jit and "line" or "count", 100) -- 0 timeout, hook triggers cancelslation when reaching the specified count
65
66local t0= os.time()
67while os.time()-t0 < 5 do
68 st= lane9.status
69 io.stderr:write((i==1) and st.." " or '.')
70 if st~="running" then break end
71end
72PRINT(" "..st)
73assert(st == "cancelled", "st is '" .. st .. "' instead of 'cancelled'")
74 42
75-- cancellation of lanes waiting on a linda 43-- cancellation of lanes waiting on a linda
76local limited = lanes_linda("limited") 44local limited = lanes_linda{name = "limited"}
77assert.fails(function() limited:limit("key", -1) end) 45assert.fails(function() limited:limit("key", -1) end)
78assert.failsnot(function() limited:limit("key", 1) end) 46assert.failsnot(function() limited:limit("key", 1) end)
79-- [[################################################ 47-- [[################################################
80limited:send("key", "hello") -- saturate linda 48limited:send("key", "hello") -- saturate linda, so that subsequent sends will block
81for k, v in pairs(limited:dump()) do 49for k, v in pairs(limited:dump()) do
82 PRINT("limited[" .. tostring(k) .. "] = " .. tostring(v)) 50 PRINT("limited[" .. tostring(k) .. "] = " .. tostring(v))
83end 51end
@@ -88,11 +56,15 @@ local wait_send = function()
88end 56end
89 57
90local wait_send_lane = lanes_gen("*", { name = 'auto' }, wait_send)() 58local wait_send_lane = lanes_gen("*", { name = 'auto' }, wait_send)()
91repeat until wait_send_lane.status == "waiting" 59repeat
92print "wait_send_lane is waiting" 60 io.stderr:write('!')
61 -- currently mingw64 builds can deadlock if we cancel the lane too early (before the linda blocks, at it causes the linda condvar not to be signalled)
62 lanes.sleep(0.1)
63until wait_send_lane.status == "waiting"
64PRINT "wait_send_lane is waiting"
93wait_send_lane:cancel() -- hard cancel, 0 timeout 65wait_send_lane:cancel() -- hard cancel, 0 timeout
94repeat until wait_send_lane.status == "cancelled" 66repeat until wait_send_lane.status == "cancelled"
95print "wait_send_lane is cancelled" 67PRINT "wait_send_lane is cancelled"
96--################################################]] 68--################################################]]
97local wait_receive = function() 69local wait_receive = function()
98 local k, v 70 local k, v
@@ -101,22 +73,30 @@ local wait_receive = function()
101end 73end
102 74
103local wait_receive_lane = lanes_gen("*", { name = 'auto' }, wait_receive)() 75local wait_receive_lane = lanes_gen("*", { name = 'auto' }, wait_receive)()
104repeat until wait_receive_lane.status == "waiting" 76repeat
105print "wait_receive_lane is waiting" 77 io.stderr:write('!')
78 -- currently mingw64 builds can deadlock if we cancel the lane too early (before the linda blocks, at it causes the linda condvar not to be signalled)
79 lanes.sleep(0.1)
80until wait_receive_lane.status == "waiting"
81PRINT "wait_receive_lane is waiting"
106wait_receive_lane:cancel() -- hard cancel, 0 timeout 82wait_receive_lane:cancel() -- hard cancel, 0 timeout
107repeat until wait_receive_lane.status == "cancelled" 83repeat until wait_receive_lane.status == "cancelled"
108print "wait_receive_lane is cancelled" 84PRINT "wait_receive_lane is cancelled"
109--################################################]] 85--################################################]]
110local wait_receive_batched = function() 86local wait_receive_batched = function()
111 local k, v1, v2 87 local k, v1, v2
112 set_finalizer(function() print("wait_receive_batched", k, v1, v2) end) 88 set_finalizer(function() print("wait_receive_batched", k, v1, v2) end)
113 k, v1, v2 = limited:receive(limited.batched, "dummy", 2) -- infinite timeout, returns only when lane is cancelled 89 k, v1, v2 = limited:receive_batched("dummy", 2) -- infinite timeout, returns only when lane is cancelled
114end 90end
115 91
116local wait_receive_batched_lane = lanes_gen("*", { name = 'auto' }, wait_receive_batched)() 92local wait_receive_batched_lane = lanes_gen("*", { name = 'auto' }, wait_receive_batched)()
117repeat until wait_receive_batched_lane.status == "waiting" 93repeat
118print "wait_receive_batched_lane is waiting" 94 io.stderr:write('!')
95 -- currently mingw64 builds can deadlock if we cancel the lane too early (before the linda blocks, at it causes the linda condvar not to be signalled)
96 lanes.sleep(0.1)
97until wait_receive_batched_lane.status == "waiting"
98PRINT "wait_receive_batched_lane is waiting"
119wait_receive_batched_lane:cancel() -- hard cancel, 0 timeout 99wait_receive_batched_lane:cancel() -- hard cancel, 0 timeout
120repeat until wait_receive_batched_lane.status == "cancelled" 100repeat until wait_receive_batched_lane.status == "cancelled"
121print "wait_receive_batched_lane is cancelled" 101PRINT "wait_receive_batched_lane is cancelled"
122--################################################]] 102--################################################]]
diff --git a/unit_tests/scripts/lane/tasking_cancelling_with_hook.lua b/unit_tests/scripts/lane/tasking_cancelling_with_hook.lua
new file mode 100644
index 0000000..56b934f
--- /dev/null
+++ b/unit_tests/scripts/lane/tasking_cancelling_with_hook.lua
@@ -0,0 +1,68 @@
1local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure(config).configure()
2print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2)
3local lanes = require_lanes_result_1
4
5local require_assert_result_1, require_assert_result_2 = require "_assert"
6print("require_assert_result:", require_assert_result_1, require_assert_result_2)
7
8local utils = lanes.require "_utils"
9local PRINT = utils.MAKE_PRINT()
10
11-- ##################################################################################################
12-- ##################################################################################################
13-- ##################################################################################################
14
15local function task(a, b, c)
16 lane_threadname("task("..a..","..b..","..c..")")
17 --error "111" -- testing error messages
18 assert(hey)
19 local v=0
20 for i=a,b,c do
21 v= v+i
22 end
23 return v, hey
24end
25
26local gc_cb = function(name_, status_)
27 PRINT(" ---> lane '" .. name_ .. "' collected with status '" .. status_ .. "'")
28end
29
30-- ##################################################################################################
31-- ##################################################################################################
32-- ##################################################################################################
33
34local generator = lanes.gen("", { name = 'auto', globals={hey=true}, gc_cb = gc_cb }, task)
35
36local N = 999999999
37local lane_h = generator(1,N,1) -- huuuuuuge...
38
39-- Wait until state changes "pending"->"running"
40--
41local st
42local t0 = os.time()
43while os.time()-t0 < 5 do
44 st = lane_h.status
45 io.stderr:write((i==1) and st.." " or '.')
46 if st~="pending" then break end
47end
48PRINT(" "..st)
49
50if st == "error" then
51 local _ = lane_h[0] -- propagate the error here
52end
53if st == "done" then
54 error("Looping to "..N.." was not long enough (cannot test cancellation)")
55end
56assert(st == "running", "st == " .. st)
57
58-- when running under luajit, the function is JIT-ed, and the instruction count isn't hit, so we need a different hook
59lane_h:cancel(jit and "line" or "count", 100) -- 0 timeout, hook triggers cancelslation when reaching the specified count
60
61local t0 = os.time()
62while os.time()-t0 < 5 do
63 st = lane_h.status
64 io.stderr:write((i==1) and st.." " or '.')
65 if st~="running" then break end
66end
67PRINT(" "..st)
68assert(st == "cancelled", "st is '" .. st .. "' instead of 'cancelled'")
diff --git a/unit_tests/scripts/lane/tasking_comms_criss_cross.lua b/unit_tests/scripts/lane/tasking_comms_criss_cross.lua
index 497e81d..610da8b 100644
--- a/unit_tests/scripts/lane/tasking_comms_criss_cross.lua
+++ b/unit_tests/scripts/lane/tasking_comms_criss_cross.lua
@@ -42,7 +42,7 @@ local tc = lanes_gen("io", { name = 'auto', gc_cb = gc_cb },
42 end 42 end
43) 43)
44 44
45local linda= lanes_linda("criss cross") 45local linda= lanes_linda{name = "criss cross"}
46 46
47local a,b= tc(linda, "A","B"), tc(linda, "B","A") -- launching two lanes, twisted comms 47local a,b= tc(linda, "A","B"), tc(linda, "B","A") -- launching two lanes, twisted comms
48 48
diff --git a/unit_tests/scripts/lane/tasking_communications.lua b/unit_tests/scripts/lane/tasking_communications.lua
index 1fd43b0..01842b4 100644
--- a/unit_tests/scripts/lane/tasking_communications.lua
+++ b/unit_tests/scripts/lane/tasking_communications.lua
@@ -72,7 +72,7 @@ local chunk= function(linda)
72 WR("chunk ", "Lane ends!\n") 72 WR("chunk ", "Lane ends!\n")
73end 73end
74 74
75local linda = lanes_linda("communications") 75local linda = lanes_linda{name = "communications"}
76assert(type(linda) == "userdata" and tostring(linda) == "Linda: communications") 76assert(type(linda) == "userdata" and tostring(linda) == "Linda: communications")
77 -- 77 --
78 -- ["->"] master -> slave 78 -- ["->"] master -> slave
@@ -90,7 +90,7 @@ local b,x,y,z,w = linda:get("<->", 4)
90assert(b == 3 and x == "x" and y == "y" and z == "z" and w == nil) 90assert(b == 3 and x == "x" and y == "y" and z == "z" and w == nil)
91local k, x = linda:receive("<->") 91local k, x = linda:receive("<->")
92assert(k == "<->" and x == "x") 92assert(k == "<->" and x == "x")
93local k,y,z = linda:receive(linda.batched, "<->", 2) 93local k,y,z = linda:receive_batched("<->", 2)
94assert(k == "<->" and y == "y" and z == "z") 94assert(k == "<->" and y == "y" and z == "z")
95linda:set("<->") 95linda:set("<->")
96local b,x,y,z,w = linda:get("<->", 4) 96local b,x,y,z,w = linda:get("<->", 4)
diff --git a/unit_tests/scripts/lane/tasking_join_test.lua b/unit_tests/scripts/lane/tasking_join_test.lua
index 2fbce6c..495a709 100644
--- a/unit_tests/scripts/lane/tasking_join_test.lua
+++ b/unit_tests/scripts/lane/tasking_join_test.lua
@@ -30,14 +30,19 @@ end
30 30
31PRINT("---=== :join test ===---", "\n\n") 31PRINT("---=== :join test ===---", "\n\n")
32 32
33-- a lane body that returns nothing is successfully joined with true, nil
34local r, ret = lanes_gen(function() end)():join()
35assert(r == true and ret == nil)
36
33-- NOTE: 'unpack()' cannot be used on the lane handle; it will always return nil 37-- NOTE: 'unpack()' cannot be used on the lane handle; it will always return nil
34-- (unless [1..n] has been read earlier, in which case it would seemingly 38-- (unless [1..n] has been read earlier, in which case it would seemingly
35-- work). 39-- work).
36 40
37local S= lanes_gen("table", { name = 'auto', gc_cb = gc_cb }, 41local S = lanes_gen("table", { name = 'auto', gc_cb = gc_cb },
38 function(arg) 42 function(arg)
39 lane_threadname "join test lane" 43 lane_threadname "join test lane"
40 set_finalizer(function() end) 44 set_finalizer(function() end)
45 -- take arg table, reverse its contents in aux, then return the unpacked result
41 local aux= {} 46 local aux= {}
42 for i, v in ipairs(arg) do 47 for i, v in ipairs(arg) do
43 table.insert(aux, 1, v) 48 table.insert(aux, 1, v)
@@ -46,15 +51,16 @@ local S= lanes_gen("table", { name = 'auto', gc_cb = gc_cb },
46 return (unpack or table.unpack)(aux) 51 return (unpack or table.unpack)(aux)
47end) 52end)
48 53
49h= S { 12, 13, 14 } -- execution starts, h[1..3] will get the return values 54local h = S { 12, 13, 14 } -- execution starts, h[1..3] will get the return values
50-- wait a bit so that the lane has a chance to set its debug name 55-- wait a bit so that the lane has a chance to set its debug name
51SLEEP(0.5) 56SLEEP(0.5)
52print("joining with '" .. h:get_threadname() .. "'") 57print("joining with '" .. h:get_threadname() .. "'")
53local a,b,c,d= h:join() 58local r, a, b, c, d = h:join()
54if h.status == "error" then 59if h.status == "error" then
55 print(h:get_threadname(), "error: " , a, b, c, d) 60 print(h:get_threadname(), "error: " , r, a, b, c, d)
56else 61else
57 print(h:get_threadname(), a,b,c,d) 62 print(h:get_threadname(), r, a, b, c, d)
63 assert(r==true, "r == " .. tostring(r))
58 assert(a==14, "a == " .. tostring(a)) 64 assert(a==14, "a == " .. tostring(a))
59 assert(b==13, "b == " .. tostring(b)) 65 assert(b==13, "b == " .. tostring(b))
60 assert(c==12, "c == " .. tostring(c)) 66 assert(c==12, "c == " .. tostring(c))
diff --git a/unit_tests/scripts/lane/tasking_send_receive_code.lua b/unit_tests/scripts/lane/tasking_send_receive_code.lua
index e329a88..fdc2602 100644
--- a/unit_tests/scripts/lane/tasking_send_receive_code.lua
+++ b/unit_tests/scripts/lane/tasking_send_receive_code.lua
@@ -53,28 +53,26 @@ local function chunk2(linda)
53 assert(info.linedefined == 32, "bad linedefined") -- start of 'chunk2' 53 assert(info.linedefined == 32, "bad linedefined") -- start of 'chunk2'
54 assert(config.strip_functions and info.currentline==-1 or info.currentline > info.linedefined, "bad currentline") -- line of 'debug.getinfo' 54 assert(config.strip_functions and info.currentline==-1 or info.currentline > info.linedefined, "bad currentline") -- line of 'debug.getinfo'
55 assert(info.lastlinedefined > info.currentline, "bad lastlinedefined") -- end of 'chunk2' 55 assert(info.lastlinedefined > info.currentline, "bad lastlinedefined") -- end of 'chunk2'
56 local k,func= linda:receive("down") 56 assert(linda:count("down") == 2, "bad linda contents") -- function, "ok"
57 assert(type(func)=="function", "not a function") 57 local k,func,str= linda:receive_batched("down", 2)
58 assert(k=="down") 58 assert(k=="down")
59 assert(type(func)=="function", "not a function")
60 assert(str=="ok", "bad receive result: " .. tostring(k) .. " -> ".. tostring(str))
61 assert(linda:count("down") == 0, "bad linda contents") -- nothing
59 62
60 func(linda) 63 func(linda)
61
62 local k,str= linda:receive("down")
63 assert(str=="ok", "bad receive result")
64
65 linda:send("up", function() return ":)" end, "ok2") 64 linda:send("up", function() return ":)" end, "ok2")
66end 65end
67 66
68local linda = lanes_linda("auto") 67local linda = lanes_linda{name = "auto"}
69local t2= lanes_gen("debug,package,string,io", { name = 'auto', gc_cb = gc_cb }, chunk2)(linda) -- prepare & launch 68local t2= lanes_gen("debug,package,string,io", { name = 'auto', gc_cb = gc_cb }, chunk2)(linda) -- prepare & launch
70linda:send("down", function(linda) linda:send("up", "ready!") end, 69linda:send("down", function(linda) linda:send("up", "ready!") end, "ok")
71 "ok")
72-- wait to see if the tiny function gets executed 70-- wait to see if the tiny function gets executed
73-- 71--
74local k,s= linda:receive(1, "up") 72local k,s= linda:receive(1, "up")
75if t2.status == "error" then 73if t2.status == "error" then
76 PRINT("t2 error: " , t2:join()) 74 local n,err,s = t2:join()
77 assert(false) 75 assert(false, "t2 error: " .. err)
78end 76end
79PRINT(s) 77PRINT(s)
80assert(s=="ready!", s .. " is not 'ready!'") 78assert(s=="ready!", s .. " is not 'ready!'")
diff --git a/unit_tests/scripts/lane/uncooperative_shutdown.lua b/unit_tests/scripts/lane/uncooperative_shutdown.lua
index 89e1ff8..eb89ed3 100644
--- a/unit_tests/scripts/lane/uncooperative_shutdown.lua
+++ b/unit_tests/scripts/lane/uncooperative_shutdown.lua
@@ -8,7 +8,7 @@ local lanes = require "lanes".configure{shutdown_timeout = 0.001, on_state_creat
8-- launch lanes that blocks forever 8-- launch lanes that blocks forever
9local lane = function() 9local lane = function()
10 local fixture = require "fixture" 10 local fixture = require "fixture"
11 fixture.sleep_for() 11 fixture.block_for()
12end 12end
13 13
14-- the generator 14-- the generator