doing sleep breaks a coroutine
12354fdw opened this issue ยท 7 comments
Minecraft Version
1.20.1
Version
1.96.0
Details
When I try to make a script like this
local i = 1
coroutine.wrap(function()
while true do
print(i)
i = i+1
sleep(1)
end
end)()
the coroutine is stopped at the first iteration
so if i call sleep()
os.pullevent("timer") should trigger and then i can resume it?
EDIT:
if not, how could i make it resume the coroutine?
that's working as expected, you need to resume the coroutine after sleep. Since sleep internally invokes coroutine.yield
to fetch timer from java LuaVM
If you'd like to use some kind of js like API, you can try coroutinex
Coroutines are commonly an xy problem, what are you trying to do with this coroutine, there's probably an easier way to do it (commonly the parallel API).
Mentioning the parallel API, it can be a good reference implementation for how to use coroutines.
If you really do have to use the coroutine API then you need to capture the wrapped coroutine and resume it with coroutine.resume
. I would use this guide for more information: https://web.archive.org/web/20230213155922/http://www.computercraft.info/forums2/index.php?/topic/25670-bbs-guide-to-coroutines/
so i need another coroutine just to resume it?
In Lua, there is nothing really executing parallel, and Lua do not have the event cycle you have in JS. Therefore, you have to control how they executes manually.
coroutine.wrap
is not magic. It just a wraps coroutine.resume
to the function it returns. You still have to continuously invoking the function it returns to resume the coroutine.
A basic example is:
local thread = coroutine.create(function()
local i = 0
while true do
print(i)
i = i+1
sleep(1)
end
end)
local res = table.pack(coroutine.resume(thread))
while coroutine.status(thread) ~= 'dead' do
res = table.pack(coroutine.resume(thread, coroutine.yield(table.unpack(res, 2, res.n))))
end
Or if you prefer coroutine.wrap
:
local resumeFn = coroutine.wrap(function()
local i = 0
while true do
print(i)
i = i+1
sleep(1)
end
end)
local res = table.pack(resumeFn())
while true do -- resumeFn will throw "cannot resume dead coroutine" when invoking, you may have to catch that
res = table.pack(resumeFn(coroutine.yield(table.unpack(res, 1, res.n))))
end
If you really do have to use the coroutine API then you need to capture the wrapped coroutine and resume it with
coroutine.resume
. I would use this guide for more information: https://web.archive.org/web/20230213155922/http://www.computercraft.info/forums2/index.php?/topic/25670-bbs-guide-to-coroutines/
Btw some information in the post is outdated. In CC: T, coroutine is not creating Java thread anymore, so it's safe to create thousand coroutines as long as you won't use all the space of the os queue