aboutsummaryrefslogtreecommitdiff
path: root/tests/cancel.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tests/cancel.lua')
-rw-r--r--tests/cancel.lua162
1 files changed, 117 insertions, 45 deletions
diff --git a/tests/cancel.lua b/tests/cancel.lua
index 6429487..0d9d143 100644
--- a/tests/cancel.lua
+++ b/tests/cancel.lua
@@ -27,9 +27,29 @@ linda:set( "lock")
27linda:limit( "atomic", -1) 27linda:limit( "atomic", -1)
28linda:set( "atomic") 28linda:set( "atomic")
29 29
30-- a numeric value to read
31linda:set( "val", 33.0)
32
33print "test OK"
30--#################################################################### 34--####################################################################
31 35
32local laneBody = function( timeout_) 36local waitCancellation = function( h, expected_status)
37 local l = lanes.linda()
38 if expected_status ~= "running" then
39 repeat
40 -- print( "lane status:", h.status)
41 l:receive( 0.1, "yeah") -- wait a bit
42 until h.status ~= "running"
43 end
44 print( "lane status:", h.status)
45 assert( h.status == expected_status, h.status .. " ~= " .. expected_status)
46 print "test OK"
47end
48
49local laneBody = function( mode_, payload_)
50 local name = "laneBody("..tostring(mode_)..","..tostring(payload_)..")"
51 set_debug_threadname( name)
52
33 set_finalizer( function( err, stk) 53 set_finalizer( function( err, stk)
34 if err == lanes.cancel_error then 54 if err == lanes.cancel_error then
35 -- note that we don't get the cancel_error when running wrapped inside a protected call if it doesn't rethrow it 55 -- note that we don't get the cancel_error when running wrapped inside a protected call if it doesn't rethrow it
@@ -41,14 +61,39 @@ local laneBody = function( timeout_)
41 end 61 end
42 end) 62 end)
43 63
44 print( " entering lane with " .. tostring( timeout_) .. " timeout") 64 print( " entering " , name)
45 repeat 65 repeat
46 -- block-wait to be hard-cancelled 66 if mode_ == "receive" then
47 print " lane calling receive()" 67 -- linda mode
48 local key, val = linda:receive( timeout_, "boob") 68 io.stdout:write( " lane calling receive() ... ")
49 print( " receive() -> ", lanes.cancel_error == key and "cancel_error" or tostring( key), tostring( val)) 69 local key, val = linda:receive( payload_, "boob")
70 print( lanes.cancel_error == key and "cancel_error" or tostring( key), tostring( val))
71 if key == lanes.cancel_error then
72 break -- gracefully abort loop
73 end
74 elseif mode_ == "get" then
75 -- busy wait mode getting data from the linda
76 io.stdout:write( " lane busy waiting ... ")
77 for i = 1, payload_ do
78 -- force a non-jitable call
79 local a = linda:get( "val")
80 a = a * 2
81 end
82 print( "again?")
83 elseif mode_ == "busy" then
84 -- busy wait mode in pure Lua code
85 io.stdout:write( " lane busy waiting ... ")
86 local a = linda:get( "val")
87 for i = 1, payload_ do
88 a = a * 2
89 a = math.sin( a) * math.sin( a) + math.cos( a) * math.cos( a) -- aka 1
90 end
91 print( "again?")
92 else
93 error "no mode: raise an error"
94 end
50 until cancel_test() -- soft cancel self test 95 until cancel_test() -- soft cancel self test
51 print " shutting down after breaking out of loop" 96 print " lane shutting down after breaking out of loop"
52end 97end
53 98
54local protectedBody = function( ...) 99local protectedBody = function( ...)
@@ -61,7 +106,8 @@ local protectedBody = function( ...)
61 -- Lua 5.1 doesn't pass additional xpcall arguments to the called function 106 -- Lua 5.1 doesn't pass additional xpcall arguments to the called function
62 -- therefore we need to create a closure that has no arguments but pulls everything from its upvalue 107 -- therefore we need to create a closure that has no arguments but pulls everything from its upvalue
63 local params = {...} 108 local params = {...}
64 local paramLessClosure = function() laneBody(table.unpack( params)) end 109 local unpack = table.unpack or unpack -- unpack for 5.1, table.unpack for 5.2+
110 local paramLessClosure = function() laneBody(unpack( params)) end
65 local status, message = xpcall( paramLessClosure, errorHandler) 111 local status, message = xpcall( paramLessClosure, errorHandler)
66 if status == false then 112 if status == false then
67 print( " error handler rethrowing '" .. (ce == message and "cancel_error"or tostring( message)) .. "'") 113 print( " error handler rethrowing '" .. (ce == message and "cancel_error"or tostring( message)) .. "'")
@@ -71,66 +117,92 @@ local protectedBody = function( ...)
71end 117end
72 118
73--#################################################################### 119--####################################################################
120--####################################################################
121
122print "\n\n####################################################################\nbegin linda cancel test\n"
123h = lanes.gen( "*", laneBody)( "receive", nil) -- start an infinite wait on the linda
124
125print "wait 1s"
126linda:receive( 1, "yeah")
127
128-- linda cancel: linda:receive() returns cancel_error immediately
129linda:cancel( "both")
130
131-- wait until cancellation is effective.
132waitCancellation( h, "done")
133
134-- reset the linda so that the other tests work
135linda:cancel( "none")
74 136
75print "####################################################################\nbegin soft cancel test\n" 137print "\n\n####################################################################\nbegin soft cancel test\n"
76h = lanes.gen("*", protectedBody)( 0.666) 138h = lanes.gen( "*", protectedBody)( "receive") -- start an infinite wait on the linda
77print "wait 3s"
78linda:receive( 3, "yeah")
79 139
80-- soft cancel 140print "wait 1s"
81print "soft cancel with awakening" 141linda:receive( 1, "yeah")
82h:cancel( -1, true)
83 142
84-- wait 10s: the lane will interrupt its loop and print the exit message 143-- soft cancel, no awakening of waiting linda operations, should timeout
144local a, b = h:cancel( "soft", 1, false)
145-- cancellation should fail as the lane is still waiting on its linda
146assert( a == false and b == "timeout")
147waitCancellation( h, "waiting")
148
149-- soft cancel, this time awakens waiting linda operations, which returns cancel_error immediately, no timeout.
150h:cancel( "soft", true)
151
152-- wait until cancellation is effective. the lane will interrupt its loop and print the exit message
153waitCancellation( h, "done")
154
155-- do return end
156
157print "\n\n####################################################################\nbegin hook cancel test\n"
158h = lanes.gen( "*", protectedBody)( "get", 300000)
85print "wait 2s" 159print "wait 2s"
86linda:receive( 2, "yeah") 160linda:receive( 2, "yeah")
87 161
88--#################################################################### 162-- count hook cancel after 3 instructions
163h:cancel( "count", 300, 5.0)
164
165-- wait until cancellation is effective. the lane will interrupt its loop and print the exit message
166waitCancellation( h, "cancelled")
89 167
90print "\n\n####################################################################\nbegin hard cancel test\n" 168print "\n\n####################################################################\nbegin hard cancel test\n"
91h = lanes.gen("*", protectedBody)() 169h = lanes.gen( "*", protectedBody)( "receive", nil) -- infinite timeout
92 170
93-- wait 3s before cancelling the lane 171-- wait 2s before cancelling the lane
94print "wait 3s" 172print "wait 2s"
95linda:receive( 3, "yeah") 173linda:receive( 2, "yeah")
96 174
97-- hard cancel and wait 10s: the lane will be interrupted from inside its current linda:receive() and won't return from it 175-- hard cancel: the lane will be interrupted from inside its current linda:receive() and won't return from it
98print "hard cancel (always awakens)"
99h:cancel() 176h:cancel()
100 177
101print "wait 5s" 178-- wait until cancellation is effective. the lane will be stopped by the linda operation throwing an error
102linda:receive( 5, "yeah") 179waitCancellation( h, "cancelled")
103
104--####################################################################
105 180
106print "\n\n####################################################################\nbegin hard cancel test with unprotected lane body\n" 181print "\n\n####################################################################\nbegin hard cancel test with unprotected lane body\n"
107h = lanes.gen("*", laneBody)() 182h = lanes.gen( "*", laneBody)( "receive", nil)
108 183
109-- wait 3s before cancelling the lane 184-- wait 2s before cancelling the lane
110print "wait 3s" 185print "wait 2s"
111linda:receive( 3, "yeah") 186linda:receive( 2, "yeah")
112 187
113-- hard cancel: the lane will be interrupted from inside its current linda:receive() and won't return from it 188-- hard cancel: the lane will be interrupted from inside its current linda:receive() and won't return from it
114print "hard cancel (always awakens)"
115h:cancel() 189h:cancel()
116 190
117print "wait 5s" 191-- wait until cancellation is effective. the lane will be stopped by the linda operation throwing an error
118linda:receive( 5, "yeah") 192waitCancellation( h, "cancelled")
119 193
120--#################################################################### 194print "\n\n####################################################################\nbegin kill cancel test\n"
121print "\n\n####################################################################\nbegin linda cancel test\n" 195h = lanes.gen( "*", laneBody)( "busy", 50000000) -- start a pure Lua busy loop lane
122h = lanes.gen("*", laneBody)()
123 196
124-- wait 3s before cancelling the lane 197-- wait 1/3s before cancelling the lane, before the busy loop can finish
125print "wait 3s" 198print "wait 0.3s"
126linda:receive( 3, "yeah") 199linda:receive( 0.3, "yeah")
127 200
128-- linda cancel: the lane will be interrupted from inside its current linda:receive() and won't return from it 201-- hard cancel with kill: the lane thread will be forcefully terminated
129print "linda cancel (always awakens the lane)" 202h:cancel( true)
130linda:cancel( "both")
131 203
132print "wait 5s" 204-- wait until cancellation is effective. the lane will be stopped by the linda operation throwing an error
133linda:receive( 5, "yeah") 205waitCancellation( h, "killed")
134 206
135--#################################################################### 207--####################################################################
136 208