This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Hirsu's profile picture

[Error] Too long without yielding

Started by Hirsu, 27 October 2012 - 05:51 PM
Hirsu #1
Posted 27 October 2012 - 07:51 PM
Hi,

I've written a program for my mining turtle which digs out a 7x7x9 chunk. It also keeps the surrounding chunks loaded using world anchors, places a torch in the middle of the chunk and auto refuels and drops off items using ender chests.

The code to run through one chunk works just fine.

However, if I try running the code in a loop (either a for loop or a while true loop), I'm getting

chunkminer:7: Too long without yielding

I've no idea how to resolve this issue. I tried looking for possible solutions but the few posts I could find didn't offer any solution. Some people on mIRC tried to help me as well but they couldn't find a solution either.
Could you guys take a quick look at the code please?

Here it is:

http://pastebin.com/dZHY74HM

Any help would be greatly appreciated! =)

Edit: piece of topic title went missing.
Orwell #2
Posted 27 October 2012 - 08:06 PM
When layer equals 4, then the bottom loop equals:

while true do
	fuel()
	while layer ~= 4 do
	  -- unreached code
	end
end

And the function fuel doesn't yield. You're code needs yield now and then, this means that it pauses until other code (coroutines) has executed some code. To make the loop yield, put 'sleep(0)' or 'coroutine.yield()' in the bottom loop.
Hirsu #3
Posted 27 October 2012 - 08:31 PM
When layer equals 4, then the bottom loop equals:

while true do
	fuel()
	while layer ~= 4 do
	  -- unreached code
	end
end

And the function fuel doesn't yield. You're code needs yield now and then, this means that it pauses until other code (coroutines) has executed some code. To make the loop yield, put 'sleep(0)' or 'coroutine.yield()' in the bottom loop.

And where exactly in the while true do loop should I put the sleep(0)? Is there any particular place I need to put that in, and why there exactly? Also, why do some loops need the sleep() added to it whilest some others dont?

Sorry about all the questions, I'm just trying to wrap my head around this so I know 1. what I'm doing 2. how to implement it in the future =)

And thanks for the quick reply!
Orwell #4
Posted 27 October 2012 - 08:43 PM
I suggest you to read about coroutines in lua. :D/>/>
Basically, you're code needs to pause now and then to let other code run for a while. This is called yielding. Your code will yield when using coroutine.yield() or any functions using that (like os.pullEvent() and sleep()). When your code doesn't yield for too long, it will be stopped with the error "too long without yielding".

Now to look at your code… Try to imagine the flow of your program when the variable 'layer' equals 4. It won't go into the "while layer ~= 4 do" loop, but it will still call fuel() all the time. In the fuel function, when the fuel level is higher than 250, it will skip that code block and basically do nothing. So it will just go in and out fuel all the time, without letting the code yield ever.

So to fix this you could 1. add sleep(0) or coroutine.yield() in the bottom while true loop (above the call to fuel() for example, doesn't really matter, as long as your program passes there)
or 2. a better solution would be to make the loop stop when it's done. Because now, as soon as layer equals 4, it will keep on running for ever while doing absolutely nothing.
Lyqyd #5
Posted 27 October 2012 - 08:44 PM
If the loop doesn't yield (turtle movements, os.pullEvent(), read(), sleep(), etc.) for ten seconds, it'll throw that error. So, something needs to yield eventually. That's why some loops that run for a long time need to have a sleep(0).
Hirsu #6
Posted 27 October 2012 - 10:20 PM
Thanks guys, I finally got it to work! I had to use coroutine.yield() and change the way I structured my while true do loop a bit. As usual, seems logical in hindsight but I just couldn't wrap my head around it (I got no experience programming whatsoever).

Now it's time for some sleep()!