diff options
Diffstat (limited to 'testes/coroutine.lua')
-rw-r--r-- | testes/coroutine.lua | 62 |
1 files changed, 53 insertions, 9 deletions
diff --git a/testes/coroutine.lua b/testes/coroutine.lua index 17f6ceba..02536ee5 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua | |||
@@ -156,11 +156,6 @@ do | |||
156 | st, msg = coroutine.close(co) | 156 | st, msg = coroutine.close(co) |
157 | assert(st and msg == nil) | 157 | assert(st and msg == nil) |
158 | 158 | ||
159 | |||
160 | -- cannot close the running coroutine | ||
161 | local st, msg = pcall(coroutine.close, coroutine.running()) | ||
162 | assert(not st and string.find(msg, "running")) | ||
163 | |||
164 | local main = coroutine.running() | 159 | local main = coroutine.running() |
165 | 160 | ||
166 | -- cannot close a "normal" coroutine | 161 | -- cannot close a "normal" coroutine |
@@ -169,20 +164,19 @@ do | |||
169 | assert(not st and string.find(msg, "normal")) | 164 | assert(not st and string.find(msg, "normal")) |
170 | end))() | 165 | end))() |
171 | 166 | ||
172 | -- cannot close a coroutine while closing it | 167 | do -- close a coroutine while closing it |
173 | do | ||
174 | local co | 168 | local co |
175 | co = coroutine.create( | 169 | co = coroutine.create( |
176 | function() | 170 | function() |
177 | local x <close> = func2close(function() | 171 | local x <close> = func2close(function() |
178 | coroutine.close(co) -- try to close it again | 172 | coroutine.close(co) -- close it again |
179 | end) | 173 | end) |
180 | coroutine.yield(20) | 174 | coroutine.yield(20) |
181 | end) | 175 | end) |
182 | local st, msg = coroutine.resume(co) | 176 | local st, msg = coroutine.resume(co) |
183 | assert(st and msg == 20) | 177 | assert(st and msg == 20) |
184 | st, msg = coroutine.close(co) | 178 | st, msg = coroutine.close(co) |
185 | assert(not st and string.find(msg, "running coroutine")) | 179 | assert(st and msg == nil) |
186 | end | 180 | end |
187 | 181 | ||
188 | -- to-be-closed variables in coroutines | 182 | -- to-be-closed variables in coroutines |
@@ -289,6 +283,56 @@ do | |||
289 | end | 283 | end |
290 | 284 | ||
291 | 285 | ||
286 | do print("coroutines closing itself") | ||
287 | global <const> coroutine, string, os | ||
288 | global <const> assert, error, pcall | ||
289 | |||
290 | local X = nil | ||
291 | |||
292 | local function new () | ||
293 | return coroutine.create(function (what) | ||
294 | |||
295 | local <close>var = func2close(function (t, err) | ||
296 | if what == "yield" then | ||
297 | coroutine.yield() | ||
298 | elseif what == "error" then | ||
299 | error(200) | ||
300 | else | ||
301 | X = "Ok" | ||
302 | return X | ||
303 | end | ||
304 | end) | ||
305 | |||
306 | -- do an unprotected call so that coroutine becomes non-yieldable | ||
307 | string.gsub("a", "a", function () | ||
308 | assert(not coroutine.isyieldable()) | ||
309 | -- do protected calls while non-yieldable, to add recovery | ||
310 | -- entries (setjmp) to the stack | ||
311 | assert(pcall(pcall, function () | ||
312 | -- 'close' works even while non-yieldable | ||
313 | coroutine.close() -- close itself | ||
314 | os.exit(false) -- not reacheable | ||
315 | end)) | ||
316 | end) | ||
317 | end) | ||
318 | end | ||
319 | |||
320 | local co = new() | ||
321 | local st, msg = coroutine.resume(co, "ret") | ||
322 | assert(st and msg == nil) | ||
323 | assert(X == "Ok") | ||
324 | |||
325 | local co = new() | ||
326 | local st, msg = coroutine.resume(co, "error") | ||
327 | assert(not st and msg == 200) | ||
328 | |||
329 | local co = new() | ||
330 | local st, msg = coroutine.resume(co, "yield") | ||
331 | assert(not st and string.find(msg, "attempt to yield")) | ||
332 | |||
333 | end | ||
334 | |||
335 | |||
292 | -- yielding across C boundaries | 336 | -- yielding across C boundaries |
293 | 337 | ||
294 | local co = coroutine.wrap(function() | 338 | local co = coroutine.wrap(function() |