1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
local lanes = require "lanes" .configure{ with_timers = false}
local linda = lanes.linda()
--####################################################################
print "\n\n####################################################################\nbegin genlock & genatomic cancel test\n"
-- get a lock and a atomic operator
local lock = lanes.genlock( linda, "lock", 1)
local atomic = lanes.genatomic( linda, "atomic")
-- check that cancelled lindas give cancel_error as they should
linda:cancel()
assert( linda:get( "empty") == lanes.cancel_error)
assert( lanes.genlock( linda, "any", 1) == lanes.cancel_error)
assert( lanes.genatomic( linda, "any") == lanes.cancel_error)
-- check that lock and atomic functions return cancel_error if the linda was cancelled
assert( lock( 1) == lanes.cancel_error)
assert( lock( -1) == lanes.cancel_error)
assert( atomic( 1) == lanes.cancel_error)
-- reset the linda so that the other tests work
linda:cancel( "none")
linda:limit( "lock", -1)
linda:set( "lock")
linda:limit( "atomic", -1)
linda:set( "atomic")
--####################################################################
local laneBody = function( timeout_)
set_finalizer( function( err, stk)
if err == lanes.cancel_error then
-- note that we don't get the cancel_error when running wrapped inside a protected call if it doesn't rethrow it
print( " laneBody after cancel" )
elseif err then
print( " laneBody error: "..tostring(err))
else
print(" laneBody finalized")
end
end)
print( " entering lane with " .. tostring( timeout_) .. " timeout")
repeat
-- block-wait to be hard-cancelled
print " lane calling receive()"
local key, val = linda:receive( timeout_, "boob")
print( " receive() -> ", lanes.cancel_error == key and "cancel_error" or tostring( key), tostring( val))
until cancel_test() -- soft cancel self test
print " shutting down after breaking out of loop"
end
local protectedBody = function( ...)
local ce = lanes.cancel_error
local errorHandler = function( _msg)
-- forward the message to the main thread that will display it with a popup
print( " error handler got ", ce == _msg and "cancel_error"or tostring( _msg))
return _msg
end
-- Lua 5.1 doesn't pass additional xpcall arguments to the called function
-- therefore we need to create a closure that has no arguments but pulls everything from its upvalue
local params = {...}
local paramLessClosure = function() laneBody(table.unpack( params)) end
local status, message = xpcall( paramLessClosure, errorHandler)
if status == false then
print( " error handler rethrowing '" .. (ce == message and "cancel_error"or tostring( message)) .. "'")
-- if the error isn't rethrown, the lane's finalizer won't get it
error( message)
end
end
--####################################################################
print "####################################################################\nbegin soft cancel test\n"
h = lanes.gen("*", protectedBody)( 0.666)
print "wait 3s"
linda:receive( 3, "yeah")
-- soft cancel
print "soft cancel with awakening"
h:cancel( -1, true)
-- wait 10s: the lane will interrupt its loop and print the exit message
print "wait 2s"
linda:receive( 2, "yeah")
--####################################################################
print "\n\n####################################################################\nbegin hard cancel test\n"
h = lanes.gen("*", protectedBody)()
-- wait 3s before cancelling the lane
print "wait 3s"
linda:receive( 3, "yeah")
-- hard cancel and wait 10s: the lane will be interrupted from inside its current linda:receive() and won't return from it
print "hard cancel (always awakens)"
h:cancel()
print "wait 5s"
linda:receive( 5, "yeah")
--####################################################################
print "\n\n####################################################################\nbegin hard cancel test with unprotected lane body\n"
h = lanes.gen("*", laneBody)()
-- wait 3s before cancelling the lane
print "wait 3s"
linda:receive( 3, "yeah")
-- hard cancel: the lane will be interrupted from inside its current linda:receive() and won't return from it
print "hard cancel (always awakens)"
h:cancel()
print "wait 5s"
linda:receive( 5, "yeah")
--####################################################################
print "\n\n####################################################################\nbegin linda cancel test\n"
h = lanes.gen("*", laneBody)()
-- wait 3s before cancelling the lane
print "wait 3s"
linda:receive( 3, "yeah")
-- linda cancel: the lane will be interrupted from inside its current linda:receive() and won't return from it
print "linda cancel (always awakens the lane)"
linda:cancel( "both")
print "wait 5s"
linda:receive( 5, "yeah")
--####################################################################
print "\ndone"
|