diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-02-12 13:36:30 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-02-12 13:36:30 -0300 |
commit | bc970005ce2e258e29a5c315ea4e49f76a66586e (patch) | |
tree | 5575ca66aeddad2036df74f38fa2bed217c2801e /testes | |
parent | f79ccdca9bbe9d486d91a44a4464b99ce38de0e2 (diff) | |
download | lua-bc970005ce2e258e29a5c315ea4e49f76a66586e.tar.gz lua-bc970005ce2e258e29a5c315ea4e49f76a66586e.tar.bz2 lua-bc970005ce2e258e29a5c315ea4e49f76a66586e.zip |
'__close' methods can yield in the return of a C function
When, inside a coroutine, a C function with to-be-closed slots return,
the corresponding metamethods can yield. ('__close' metamethods called
through 'lua_closeslot' still cannot yield, as there is no continuation
to go when resuming.)
Diffstat (limited to 'testes')
-rw-r--r-- | testes/locals.lua | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/testes/locals.lua b/testes/locals.lua index 446ec13a..a93839db 100644 --- a/testes/locals.lua +++ b/testes/locals.lua | |||
@@ -707,7 +707,6 @@ if rawget(_G, "T") then | |||
707 | -- results are correct | 707 | -- results are correct |
708 | checktable(t, {10, 20}) | 708 | checktable(t, {10, 20}) |
709 | end | 709 | end |
710 | |||
711 | end | 710 | end |
712 | 711 | ||
713 | 712 | ||
@@ -930,6 +929,81 @@ assert(co == nil) -- eventually it will be collected | |||
930 | collectgarbage() | 929 | collectgarbage() |
931 | 930 | ||
932 | 931 | ||
932 | if rawget(_G, "T") then | ||
933 | print("to-be-closed variables x coroutines in C") | ||
934 | do | ||
935 | local token = 0 | ||
936 | local count = 0 | ||
937 | local f = T.makeCfunc[[ | ||
938 | toclose 1 | ||
939 | toclose 2 | ||
940 | return . | ||
941 | ]] | ||
942 | |||
943 | local obj = func2close(function (_, msg) | ||
944 | count = count + 1 | ||
945 | token = coroutine.yield(count, token) | ||
946 | end) | ||
947 | |||
948 | local co = coroutine.wrap(f) | ||
949 | local ct, res = co(obj, obj, 10, 20, 30, 3) -- will return 10, 20, 30 | ||
950 | -- initial token value, after closing 2nd obj | ||
951 | assert(ct == 1 and res == 0) | ||
952 | -- run until yield when closing 1st obj | ||
953 | ct, res = co(100) | ||
954 | assert(ct == 2 and res == 100) | ||
955 | res = {co(200)} -- run until end | ||
956 | assert(res[1] == 10 and res[2] == 20 and res[3] == 30 and res[4] == nil) | ||
957 | assert(token == 200) | ||
958 | end | ||
959 | |||
960 | do | ||
961 | local f = T.makeCfunc[[ | ||
962 | toclose 1 | ||
963 | return . | ||
964 | ]] | ||
965 | |||
966 | local obj = func2close(function () | ||
967 | local temp | ||
968 | local x <close> = func2close(function () | ||
969 | coroutine.yield(temp) | ||
970 | return 1,2,3 -- to be ignored | ||
971 | end) | ||
972 | temp = coroutine.yield("closing obj") | ||
973 | return 1,2,3 -- to be ignored | ||
974 | end) | ||
975 | |||
976 | local co = coroutine.wrap(f) | ||
977 | local res = co(obj, 10, 30, 1) -- will return only 30 | ||
978 | assert(res == "closing obj") | ||
979 | res = co("closing x") | ||
980 | assert(res == "closing x") | ||
981 | res = {co()} | ||
982 | assert(res[1] == 30 and res[2] == nil) | ||
983 | end | ||
984 | |||
985 | do | ||
986 | -- still cannot yield inside 'closeslot' | ||
987 | local f = T.makeCfunc[[ | ||
988 | toclose 1 | ||
989 | closeslot 1 | ||
990 | ]] | ||
991 | local obj = func2close(coroutine.yield) | ||
992 | local co = coroutine.create(f) | ||
993 | local st, msg = coroutine.resume(co, obj) | ||
994 | assert(not st and string.find(msg, "attempt to yield across")) | ||
995 | |||
996 | -- nor outside a coroutine | ||
997 | local f = T.makeCfunc[[ | ||
998 | toclose 1 | ||
999 | ]] | ||
1000 | local st, msg = pcall(f, obj) | ||
1001 | assert(not st and string.find(msg, "attempt to yield from outside")) | ||
1002 | end | ||
1003 | end | ||
1004 | |||
1005 | |||
1006 | |||
933 | -- to-be-closed variables in generic for loops | 1007 | -- to-be-closed variables in generic for loops |
934 | do | 1008 | do |
935 | local numopen = 0 | 1009 | local numopen = 0 |