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

coroutine.resume() not resuming coroutine after sleep() is called

Started by Nothy, 05 October 2017 - 08:16 AM
Nothy #1
Posted 05 October 2017 - 10:16 AM
Basically, I have a routine that simply prints a string, sleeps for 3 seconds and prints another string, then inevitably dies (don't worry, they don't mind it.)

The coroutine simply gets left as suspended. I'm pretty sure it's not supposed to be suspended for however long it feels like suspending for rather than 3 seconds. Any thoughts?

And here's the snippet of code in question:

local tasks = {}
--#[snip snip]
function checkTasks()
  for k,v in pairs(tasks) do
	local success, resume = coroutine.resume(v.task)
	if not resume then
	  print(v.taskID.." is dead")
	  table.remove(tasks, k)
	  break
	else
	  print(v.taskID.." isn't dead ("..tostring(coroutine.status(v.task))..")")
	  coroutine.resume(v.task)
	end
  end
end
function new( _task )
  if type(_task) == "function" then
	local index = #tasks+1
	tasks[index] = {}
	tasks[index].taskID = index
	tasks[index].task = coroutine.create(_task)
	return tasks[index].taskID
  else
	error("invalid argument #1, expected function, got "..type(_task),2)
  end
end

and the routine code:

function routine()
   print("hello")
   sleep(3)
   print("goodbye!")
end
--# tasker = the coroutine system
tasker.new(routine())
while(true) do tasker.checkTasks() sleep(0) end

EDIT: Did some research, every time the process yields, it puts the coroutine in a permanent state of being suspended.
Edited on 05 October 2017 - 08:25 AM
SquidDev #2
Posted 05 October 2017 - 10:27 AM
Your coroutine resuming function doesn't seem to pay any attention to ComputerCraft's events. You never resume coroutines with any arguments, and your sleep(0) call will empty the event queue. Thus sleep(3) will wait for a timer event but never receive one.

Instead, refer to the parallel API's implementation as this handles events correctly.

Edit: You're also creating a new task with the result of calling routine(). I'm presuming this is a typo, as otherwise your code will error when run.
Edited on 05 October 2017 - 08:32 AM
Nothy #3
Posted 05 October 2017 - 11:27 AM
Edit: You're also creating a new task with the result of calling routine(). I'm presuming this is a typo, as otherwise your code will error when run.
That's a typo, yes. Thank you for your help, I'll see if I can get this working.
Dave-ee Jones #4
Posted 05 October 2017 - 11:14 PM
Alternatively you can do a 'while' loop that pulls events and passes them to 'coroutine.resume', but that's a bit more advanced. Lot more interesting and powerful though.
Nothy #5
Posted 06 October 2017 - 09:12 AM
Alternatively you can do a 'while' loop that pulls events and passes them to 'coroutine.resume', but that's a bit more advanced. Lot more interesting and powerful though.
That's pretty much what I did. It works like a charm. Now to actually get a shell running in a window…
Dave-ee Jones #6
Posted 08 October 2017 - 11:43 PM
Alternatively you can do a 'while' loop that pulls events and passes them to 'coroutine.resume', but that's a bit more advanced. Lot more interesting and powerful though.
That's pretty much what I did. It works like a charm. Now to actually get a shell running in a window…

Mmm. Basically what you do is you run a coroutine inside the window by redirecting to that window. Here's a snippet I quickly came up with (made normal window white so you can see the new window and the shell running in it):

term.setBackgroundColor(colors.white)
term.clear()
local myCor = coroutine.create(function() shell.run("/rom/programs/shell") end)
local myWin = window.create(term.current(),5,3,10,8,true)

term.redirect(myWin)
while coroutine.status(myCor) ~= "dead" do
  local e = { os.pullEvent() }
  coroutine.resume(myCor,unpack(e))
end
term.setBackgroundColor(colors.black)
term.clear()
term.setCursorPos(1,1)

The reason I'm unpacking an event object is so the coroutine actually gets passed any events that the normal window gets. By default (if you don't do this) you won't be able to interact with the small window at all (including key presses, mouse clicks etc.), so keep that in mind.

Also, if you exit the window terminal with 'exit' you will notice it clears the screen, going back to the old terminal. Just a way of showing you how a coroutine dies (note the condition of the while loop).

Anyway, good luck!
Edited on 08 October 2017 - 09:44 PM