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

[Lua]Yeilding Infinite Loop

Started by TheDarkVoid, 09 January 2013 - 01:03 PM
TheDarkVoid #1
Posted 09 January 2013 - 02:03 PM
I'm trying to make a program for my computer that will emit a red-stone pulse forever when it's not receiving a red stone signal. This code works: http://pastebin.com/M9gv1qrJ but i get the error after a while that loop too long with out yielding. is there something like in C#
yield return null;
for lua. Is there a way to avoid this problem?
theoriginalbit #2
Posted 09 January 2013 - 02:27 PM
all you need to do is add a sleep( 0 ) somewhere in your code. this will allow it to yield.
immibis #3
Posted 09 January 2013 - 04:50 PM
All CC computers run in separate coroutines in the same Lua state. This means only one is running at a time, and they switch whenever coroutine.yield is called.
Coroutine.yield is called inside os.pullEvent and functions that use it (eg sleep, read, turtle functions, etc) so the main reason people see "too long without yielding" is if they've accidentally made an infinite loop that does nothing.

Please upload your code to pastebin and post the link here so we can see what the actual problem is here. If you just added sleep(0), then chances are you're wasting a lot of the server's CPU time.


PS. The Lua equivalent of "yield return null;" is "coroutine.yield(nil) or just "coroutine.yield()" (since everything defaults to nil) but that is not what you are looking for
ChunLing #4
Posted 09 January 2013 - 06:06 PM
Add an os.pullEvent("redstone") rather than a sleep, that way the loop only runs when there is a change in the redstone state.
TheDarkVoid #5
Posted 10 January 2013 - 12:37 AM
This is the code immibis:

print("Starting Timer: 5-.2")
while true do
while not redstone.getInput("front") do
redstone.setOutput("top", true)
os.sleep(.2)
redstone.setOutput("top", false)
os.sleep(5)
end
end
The link was there…
immibis #6
Posted 10 January 2013 - 01:02 AM
This is the code immibis:

print("Starting Timer: 5-.2")
while true do
while not redstone.getInput("front") do
redstone.setOutput("top", true)
os.sleep(.2)
redstone.setOutput("top", false)
os.sleep(5)
end
end
The link was there…
So when nobody's using the timer, the program is doing this:

Program: Is the redstone signal on yet?
CC: No.
Program: Is the redstone signal on yet?
CC: No.
Program: Is the redstone signal on yet?
CC: No.
Program: Is the redstone signal on yet?
CC: No.
Program: Is the redstone signal on yet?
CC: No.
Program: Is the redstone signal on yet?
CC: No.
Program: Is the redstone signal on yet?
CC: No.
*snip a few thousand lines*
Program: Is the redstone signal on yet?
CC: No. Shut up. *terminates program*
If you add sleep(0), you're still doing that, just slightly slower, and wasting CPU.

What you probably want is to wait for a signal instead of constantly asking about it:

print("Starting Timer: 5-.2")
while true do
 -- As long as the front input is on, wait for a redstone event (which means some signal changed, but the event doesn't say which one, so we have to keep checking)
 -- If the signal is already off, this loop doesn't do anything so we keep repeating the timer thing.
 while redstone.getInput("front") do
  os.pullEvent("redstone")
 end

 -- Then do the timer thing
 redstone.setOutput("top", true)
 os.sleep(.2)
 redstone.setOutput("top", false)
 os.sleep(5)
end
end
Lyqyd #7
Posted 10 January 2013 - 03:45 AM
Immibis' code has an extra end, it appears.
ChunLing #8
Posted 10 January 2013 - 09:05 AM
I don't get why we only check for a redstone event if the front input is on. The code presented doesn't match the description of the desired behavior.

Depending on how picky we want to be about input and emitting a pulse, this may require os.pullEvent() loop using timers rather than sleep to control the pulses.