diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-12-30 11:20:22 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-12-30 11:20:22 -0300 |
| commit | ce101dcaf73ff6d610593230d41b63c163a91519 (patch) | |
| tree | 6417f02cb96257a835fa908bfea15c2557a41413 /testes | |
| parent | 553b37ce4ff758d8cf80d48a21287526c92221c6 (diff) | |
| download | lua-ce101dcaf73ff6d610593230d41b63c163a91519.tar.gz lua-ce101dcaf73ff6d610593230d41b63c163a91519.tar.bz2 lua-ce101dcaf73ff6d610593230d41b63c163a91519.zip | |
Handles '__close' errors in coroutines in "coroutine style"
Errors in '__close' metamethods in coroutines are handled by the same
logic that handles other errors, through 'recover'.
Diffstat (limited to 'testes')
| -rw-r--r-- | testes/coroutine.lua | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/testes/coroutine.lua b/testes/coroutine.lua index 0a970e98..fbeabd07 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua | |||
| @@ -123,7 +123,7 @@ assert(#a == 22 and a[#a] == 79) | |||
| 123 | x, a = nil | 123 | x, a = nil |
| 124 | 124 | ||
| 125 | 125 | ||
| 126 | -- coroutine closing | 126 | print("to-be-closed variables in coroutines") |
| 127 | 127 | ||
| 128 | local function func2close (f) | 128 | local function func2close (f) |
| 129 | return setmetatable({}, {__close = f}) | 129 | return setmetatable({}, {__close = f}) |
| @@ -189,7 +189,6 @@ do | |||
| 189 | local st, msg = coroutine.close(co) | 189 | local st, msg = coroutine.close(co) |
| 190 | assert(st == false and coroutine.status(co) == "dead" and msg == 200) | 190 | assert(st == false and coroutine.status(co) == "dead" and msg == 200) |
| 191 | assert(x == 200) | 191 | assert(x == 200) |
| 192 | |||
| 193 | end | 192 | end |
| 194 | 193 | ||
| 195 | do | 194 | do |
| @@ -207,6 +206,44 @@ do | |||
| 207 | local st1, st2, err = coroutine.resume(co) | 206 | local st1, st2, err = coroutine.resume(co) |
| 208 | assert(st1 and not st2 and err == 43) | 207 | assert(st1 and not st2 and err == 43) |
| 209 | assert(X == 43 and Y.name == "pcall") | 208 | assert(X == 43 and Y.name == "pcall") |
| 209 | |||
| 210 | -- recovering from errors in __close metamethods | ||
| 211 | local track = {} | ||
| 212 | |||
| 213 | local function h (o) | ||
| 214 | local hv <close> = o | ||
| 215 | return 1 | ||
| 216 | end | ||
| 217 | |||
| 218 | local function foo () | ||
| 219 | local x <close> = func2close(function(_,msg) | ||
| 220 | track[#track + 1] = msg or false | ||
| 221 | error(20) | ||
| 222 | end) | ||
| 223 | local y <close> = func2close(function(_,msg) | ||
| 224 | track[#track + 1] = msg or false | ||
| 225 | return 1000 | ||
| 226 | end) | ||
| 227 | local z <close> = func2close(function(_,msg) | ||
| 228 | track[#track + 1] = msg or false | ||
| 229 | error(10) | ||
| 230 | end) | ||
| 231 | coroutine.yield(1) | ||
| 232 | h(func2close(function(_,msg) | ||
| 233 | track[#track + 1] = msg or false | ||
| 234 | error(2) | ||
| 235 | end)) | ||
| 236 | end | ||
| 237 | |||
| 238 | local co = coroutine.create(pcall) | ||
| 239 | |||
| 240 | local st, res = coroutine.resume(co, foo) -- call 'foo' protected | ||
| 241 | assert(st and res == 1) -- yield 1 | ||
| 242 | local st, res1, res2 = coroutine.resume(co) -- continue | ||
| 243 | assert(coroutine.status(co) == "dead") | ||
| 244 | assert(st and not res1 and res2 == 20) -- last error (20) | ||
| 245 | assert(track[1] == false and track[2] == 2 and track[3] == 10 and | ||
| 246 | track[4] == 10) | ||
| 210 | end | 247 | end |
| 211 | 248 | ||
| 212 | 249 | ||
