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

Coroutines?

Started by sci4me, 06 September 2013 - 09:03 PM
sci4me #1
Posted 06 September 2013 - 11:03 PM
Hey guys! So, I am trying to make a background "thread" to handle adding and removing devices, and the code works, but the coroutine doesnt actually run.. can someone explain how to do this?


if not fs.exists("dev") then
fs.makeDir("dev")
end

local deviceCoroutine = coroutine.create(function()
while true do
evt, side = os.pullEvent()
if evt == "peripheral" then 
local f = fs.open("dev/"..side, "w")
f.close()
end
if evt == "peripheral_detach" then
fs.delete("dev/"..side)
end
end
end)
coroutine.resume(deviceCoroutine)
Kingdaro #2
Posted 06 September 2013 - 11:13 PM
Once you resume the coroutine, os.pullEvent() yields it, and it never gets resumed again.

You need to run that coroutine alongside other coroutines in an event loop, and resume each of those coroutines with said events. Look at how the parallel API works for an example.
sci4me #3
Posted 06 September 2013 - 11:25 PM
Aah, I think I see. Let me try that.

Okay, just FYI, I am using a very barebones system - deleted rom and reduced bios. For the challenge. I have copied over some of the api code. I have the parallel api. I have this code here:


local deviceCoroutine = coroutine.create(function()
while true do
evt, side = os.pullEvent()
if evt == "peripheral" then 
local f = fs.open("dev/"..side, "w")
f.close()
end
if evt == "peripheral_detach" then
fs.delete("dev/"..side)
end
end
end)

waitForAny(
function()
print("Welcome to SciNux V"..os.version().." HC Edition!")
end,
function()
while true do
coroutine.resume(deviceCoroutine)
end
end )

Thats not what you meant is it? Because it doesnt do the trick..
LBPHacker #4
Posted 07 September 2013 - 02:17 AM
-snip-
Almost. But I think that errors out with "too long without yielding" (you might not be able to actually see that). That's because the second coroutine in .waitForAny runs infinitely (because of the while true do and the lack of anything that'd yield it). Do not make a coroutine of your device handling function, that's the task of the parallel API (if you decide to use it). Just have a function that handles devices:
local deviceHandler = function(...)
    -- do that what you did up there in your code
end

local theOhterOne = function(...)
    -- here runs the OS - I highly suggest to define this function here, not inside .waitForAny
    -- that would make no technical difference, but (at least for me) the code would look cleaner
end

parallel.waitForAny(deviceHandler, theOtherOne) -- .waitForAny will take care of the functions
sci4me #5
Posted 07 September 2013 - 02:56 AM
-snip-
Almost. But I think that errors out with "too long without yielding" (you might not be able to actually see that). That's because the second coroutine in .waitForAny runs infinitely (because of the while true do and the lack of anything that'd yield it). Do not make a coroutine of your device handling function, that's the task of the parallel API (if you decide to use it). Just have a function that handles devices:
local deviceHandler = function(...)
	-- do that what you did up there in your code
end

local theOhterOne = function(...)
	-- here runs the OS - I highly suggest to define this function here, not inside .waitForAny
	-- that would make no technical difference, but (at least for me) the code would look cleaner
end

parallel.waitForAny(deviceHandler, theOtherOne) -- .waitForAny will take care of the functions


local deviceHandler = function()
while true do
evt, side = os.pullEvent()
if evt == "peripheral" then 
local f = fs.open("dev/"..side, "w")
f.close()
end
if evt == "peripheral_detach" then
fs.delete("dev/"..side)
end
end
end

local os = function()
print("SciNux V"..os.version().." HC Edition"
end

waitForAny(deviceHandler, os)

Prints nothing, I assume its the too long without yielding? but that doesnt really make sense…
LBPHacker #6
Posted 07 September 2013 - 04:58 AM
  1. When I say ".waitForAny" (note the dot), I of course mean parallel.waitForAny
  2. The print in the os function misses a closing parenthesis at the end of the line
  3. Don't overwrite os
  4. The os function returns immediately, breaking the loop in .waitForAny
immibis #7
Posted 07 September 2013 - 08:59 AM
  1. When I say ".waitForAny" (note the dot), I of course mean parallel.waitForAny
  2. The print in the os function misses a closing parenthesis at the end of the line
  3. Don't overwrite os
  4. The os function returns immediately, breaking the loop in .waitForAny
He deleted bios and all of rom (as a challenge?)

Did you copy print?
sci4me #8
Posted 07 September 2013 - 04:27 PM
Yeah I copied all the functions that I am using (print, waitForAny) so.. not sure..

Yes immibis its as a challenge :D/> Kind of fun actually.

Also, I cant seem to figure out how to use the http api natively… http and http.native are both nil… with http enabled in the config…
EDIT: its a table of length 0…

Well, with a tish of investigation, I have the http working :P/> /lua noob
theoriginalbit #9
Posted 08 September 2013 - 05:26 AM
Unless you copied waitForAll/Any into the bios then it wont be in the global scope and you'll need to do an API call.

Really as more of a challenge you should not use code from the parallel API and make your own Coroutine Management API :P/> Thats what I did to get a better understanding of how coroutines work.

EDIT: its a table of length 0…
From now on use a function like this to count all elements in a table

local function count( t )
  local c = 0
  for _ in pairs(t) do
    c = c + 1
  end
  return c
end