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

coroutine stuff

Started by Exerro, 31 January 2013 - 07:38 AM
Exerro #1
Posted 31 January 2013 - 08:38 AM
ok so i was messing around with the coroutine api and it was very confusing and i couldnt make anything work. I was trying to make something get input and print it and also print an s at the bottom right (dont ask me why)
code:

function blank()
		 term.setCursorPos(1,1)
		 if event then
				 print(event, key)
		 end
		 term.setCursorPos(51,19)
		 print("S")
end
function something()
		 event, key = os.pulEvent()
end
m = coroutine.create(blank)
k = coroutine.create(something)
while true do
			 coroutine.resume(m)
			 coroutine.resume(k)
			 sleep(0.5)
			 coroutine.yield(m)
			 coroutine.yield(k)
end

I just want some advice on how to make coroutines work and how to make them useful
Lyqyd #2
Posted 31 January 2013 - 09:00 AM
Your code doesn't at all do what you think it does. coroutine.yield must be called from within the coroutine (this is what os.pullEventRaw calls), and many things yield in this manner (os.pullEvent, read, sleep, etc.).

Here is what your code does:

Declare two functions.
Create coroutines from these functions.
Resume the first coroutine. It runs through to the end and stops. It yields, and is a dead coroutine. It cannot be resumed again.
Resume the second coroutine. It runs until the call to pullEvent, at which point it yields.
Sleep for 0.5 seconds.
Yield the current coroutine, passing the dead thread value of the first coroutine back as an event filter.
If it ignores that filter (which it may not, I don't know), your coroutine "manager" loop will be resumed upon the next event.
Again yield the current coroutine, passing the thread value for our still-living thread back as a filter.
Upon the next event (assuming again that it ignores the invalid filter), resume the coroutine manager, which loops back to the beginning.
Attempt to resume dead coroutine, which if we haven't already errored or hung up waiting for events that can't exist, causes an "attempt to resume dead coroutine".
Exerro #3
Posted 01 February 2013 - 05:27 AM
so can you tell me how to get coroutines to work?
I don't even know what coroutine.yield does :l
PixelToast #4
Posted 01 February 2013 - 06:26 AM
coroutine.yeild, when called from a coroutine being called by resume will be paused
i would read teh manual :3
Lyqyd #5
Posted 01 February 2013 - 07:17 AM
so can you tell me how to get coroutines to work?
I don't even know what coroutine.yield does :l

Try looking through the parallel API, and look in bios.lua to see what os.pullEvent does. I'm not sure what you mean "get[ting] coroutines to work". They work fine, you're just using them incorrectly. Your coroutine manager needs to be yielding to retrieve events, then passing those events to your coroutines as it resumes them (like parallel does). In its simplest form:


--we first need a table of coroutines in coroutineTable.
while #coroutineTable > 0 do
  --get the next event.
  local event = {coroutine.yield()} --this is what os.pullEvent eventually calls, so we will just use it directly for clarity.
  for i = 1, #coroutineTable do
    --for every coroutine we have, resume it and give it the current event.
    coroutine.resume(coroutineTable[i], unpack(event))
  end
  --now we remove dead coroutines.
  for i = #coroutineTable, 1, -1 do
    if coroutine.status(coroutineTable[i]) == "dead" then
      table.remove(coroutineTable, i)
    end
  end
end
Exerro #6
Posted 01 February 2013 - 08:39 AM
so can you tell me how to get coroutines to work?
I don't even know what coroutine.yield does :l

Try looking through the parallel API, and look in bios.lua to see what os.pullEvent does. I'm not sure what you mean "get[ting] coroutines to work". They work fine, you're just using them incorrectly. Your coroutine manager needs to be yielding to retrieve events, then passing those events to your coroutines as it resumes them (like parallel does). In its simplest form:


--we first need a table of coroutines in coroutineTable.
while #coroutineTable > 0 do
  --get the next event.
  local event = {coroutine.yield()} --this is what os.pullEvent eventually calls, so we will just use it directly for clarity.
  for i = 1, #coroutineTable do
	--for every coroutine we have, resume it and give it the current event.
	coroutine.resume(coroutineTable[i], unpack(event))
  end
  --now we remove dead coroutines.
  for i = #coroutineTable, 1, -1 do
	if coroutine.status(coroutineTable[i]) == "dead" then
	  table.remove(coroutineTable, i)
	end
  end
end
ok thanks…this is what i needed i think (i have never used them before and couldn't find much on them) and yes i meant i wanted to get to a stage where i could use coroutines and understand them…i looked through your code but one thing doesnt make sense…does coroutine.yeild() capture events?

edit: and how does 'for i = #coroutineTable, 1, -1 do' work?
PixelToast #7
Posted 01 February 2013 - 08:45 AM
does coroutine.yeild() capture events?
only when the original coroutine yeilds
the parallel API automatically passes the event\ to coroutine.resume
edit:
edit: and how does 'for i = #coroutineTable, 1, -1 do' work?
that would work, but would count backwards :P/>
Exerro #8
Posted 01 February 2013 - 08:48 AM
does coroutine.yeild() capture events?
only when the original coroutine yeilds
the parallel API automatically passes the event\ to coroutine.resume
edit:
edit: and how does 'for i = #coroutineTable, 1, -1 do' work?
that would work, but would count backwards
ok i get the for loop thing (blonde moment :P/>) but coroutine.yeild…it pauses the coroutine it's in…and captures events that go on while the coroutine is paused and then gives a table of all the events captured?

http://computercraft.info/wiki/Coroutine <— someone needs to add to this
PixelToast #9
Posted 01 February 2013 - 08:59 AM
bah, i use the manual http://www.lua.org/manual/5.1/manual.html#5.2
Lyqyd #10
Posted 01 February 2013 - 09:00 AM
No, coroutine documentation belongs in the Lua docs, since they're straight from Lua.

The coroutine.yield in that code example is roughly equivalent to os.pullEvent. It yields to wait for a single event, then put it into a table for easy handling of the event and its parameters.

Maybe the big picture will help. Each computer in ComputerCraft is run in a coroutine. There's a coroutine manager in the Java side of things that resumes that computer's coroutine when it gets an event. It resumes that computer and passes it the event. As of this writing, the computer has two child coroutines running, being managed by the main coroutine (rednet coroutine and shell coroutine) using parallel. So, when the main coroutine of the computer is resumed, it gets the event and distributes it to its two child coroutines (the shell and rednet ones).

Basically, all coroutine.yield does is pass control back to whatever resumed it. It doesn't do anything else. Events are handled (and passed in to each computer) by the Java code that controls the computer coroutines.
Exerro #11
Posted 01 February 2013 - 09:09 AM
No, coroutine documentation belongs in the Lua docs, since they're straight from Lua.

The coroutine.yield in that code example is roughly equivalent to os.pullEvent. It yields to wait for a single event, then put it into a table for easy handling of the event and its parameters.

Maybe the big picture will help. Each computer in ComputerCraft is run in a coroutine. There's a coroutine manager in the Java side of things that resumes that computer's coroutine when it gets an event. It resumes that computer and passes it the event. As of this writing, the computer has two child coroutines running, being managed by the main coroutine (rednet coroutine and shell coroutine) using parallel. So, when the main coroutine of the computer is resumed, it gets the event and distributes it to its two child coroutines (the shell and rednet ones).

Basically, all coroutine.yield does is pass control back to whatever resumed it. It doesn't do anything else. Events are handled (and passed in to each computer) by the Java code that controls the computer coroutines.
ok that makes sense….my interpretation of this is: every computer is run with coroutines in java and each computer has 2 coroutines that is rednet&amp;shell(everything else) and so when the computer gets an event it just resumes those 2 coroutines. coroutine.yield is just the direct way of getting the events passed down by java im guessing but it will wait for the event (which effectively pauses the coroutine)
So the code you gave me will run an indefinite amount of functions simultaneously (as long as they are [coroutine functions?]) and recieve the event args as args in the function?