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

coroutine yeilding and sleep( )

Started by Exerro, 19 February 2013 - 10:19 AM
Exerro #1
Posted 19 February 2013 - 11:19 AM
I'm making a multitasking thing where you load processes and they create windows and each file can have its own process and if you use term.write / term.clear in that file it saves it to a screen table for the files processes window
( window.s[process.running[shell.getRunningProgram()].window].screen ) i think. Any way, it all works fine and prints to the screen through the screen table and a drawScreen function but i want the program being run to sleep but that always stops the code completely
sleep and coroutine.yeild make the program stop and os.pullEvent and a timer dont do a thing and pause it for about a millisecond maybe

Is there a way to pause code when its being run through a coroutine?

My code ( with comments ) :
Spoiler

process = {}
process.running = {}
function process.create( name, func ) --this creates a process that can be run later
local func = coroutine.create( func ) --creates a coroutine of the function passed in
process.running[name] = { } --makes a new slot in the process.running table for the process
process.running[name].window = window.getFree( ) --sets the slot of the window it will use
window.create( window.getFree( ) ) --makes a new window at the slot
process.running[name].co = func --sets the processes coroutine to the function passed in
end --ends the function
function process.getIndex( name, t ) --returns the index of a process
t = t or process.running --makes sure t exists
local i = 1 --sets i to 1
for k,v in pairs( t ) do --goes through all the coroutines
  if k == name then --checks if the process its at is the one the user is looking for
   return i --returns the index
  end
  local i = i+1 --goes to the next index
end
end
function process.run( name ) --runs a process
if coroutine.status( process.running[name].co ) == "dead" then --checks if its dead
  local k = process.getIndex( name, process.running ) --gets the index of the dead process
  if not k then error( "wierd" ) end --errors if it cannot find the index of a process
  table.remove( window.s, process.running[name].window ) --removes the processes window
  table.remove( process.running, k ) --removes the process
else
  coroutine.resume( process.running[name].co ) --runs the process
end
end
window = {}
window.s = { }
function window.getFree( ) --returns the first free slot
local i = 1 --sets i to 1
while true do --loops
  if not window.s[i] then --if the slot is free then
   return i --returns the index
  end
  i = i+1
  if i > 500 then --checks if it has been running too long
   return --quits the loop
  end
end
error( "no windows left" ) --errors if it cannot find a free window
end
function window.genScreen( x, y, bc, tc ) --generates a new screen
for i = 1, y do --loops through y
  screen[i] = { } --sets the y to a table
  for m = 1, x do --loops through x
   screen[i][m] = { [1] = " ", [2] = bc, [3] = tc } --sets the x to a table containing draw data
   return screen --returns the result
  end
end
error( "failed to generate screen" ) --errors if it failed to do any of the above
end
function window.create( index, x, y, bc, tc, screen, xpos, ypos ) --creates a new window
local index = index or window.getFree( ) --if no index is passed on it sets the index to the first one available
local x = x or 51 --goes through all the variables making sure they exist
local y = y or 19
local bc = bc or colours.black
local tc = tc or 1
local xpos = xpos or 1
local ypos = ypos or 1
local screen = window.genScreen( x, y, bc, tc ) --generates a screen
table.insert( window.s, index, { screen = screen, bc = bc, tc = tc, x = xpos, y = ypos } ) --inserts the window into the window.s table
end
function window.write( index, ... ) --puts strings into the window.s[index].screen table
local str = ""
for i = 1,#arg do
  str = str..tostring( arg[i] ) --joins all the args into 1 string
end
local len = string.len( str ) --gets the length of the string
local m = { }
for i = 1,len do
  table.insert( m, string.sub( str, i, i ) ) --splits all the chars into a table
end
local win = window.s[index] --sets win to the window selected table
for i = 1,#m do
  if ( i+win.x )-1 <= 51 then --makes sure it will not go off screen
   win.screen[win.y][( i+win.x )-1] = { [1] = m[i], [2] = win.bc, [3] = win.tc } --inserts the char into the processes screen
  end
end
end
screen = { }
function screen.draw( ) --draws all the screens ( will be updated )
for i = 1,#window.s do
  local s = window.s[i].screen
  for m = 1,#s do
   for k = 1,#s[m] do
	oldTerm.setCursorPos( k, m ) --sets the cursor pos
	oldTerm.setBackgroundColour( s[m][k][2] ) --sets the colour
	oldTerm.setTextColour( s[m][k][3] ) --sets the other colour
	oldTerm.write( s[m][k][1] ) --writes the char
   end
  end
end
end
oldTerm = _G["term"] --sets oldTerm to term
term = { } --removes term
function term.write( ... ) --rewrites term ( puts it into the files screen )
local prog = shell.getRunningProgram( ) --gets the file/program its being called from
if process.running[prog] then --checks if there is a process for it
  window.write( process.running[prog].window, unpack( arg ) ) --writes it
  screen.draw( ) --draws the screen
else
  error( "unknown application tried to draw to screen" ) --errors that there was no process for the function
end
end
function term.clear( )
local prog = shell.getRunningProgram( ) --gets the running program
if process.running[prog] then --checks of there is a process for it
  local win = process.running[prog].window --gets the window for the process
  window.s[win].screen = window.genScreen( #window.s[win].screen, #window.s[win].screen[1], window.s[win].bc, window.s[win].tc ) --resets it
  screen.draw( ) --draws the screen
else
  error( "unknown application tried to draw to screen" )
end
end
--the rest of the term functions will come later ( they aren't very complicated )
function runProgram( path )
process.create( path, function() shell.run( path ) end ) --creates a process for a program/file
end
runProgram( "hello" )
for z = 1,10 do
process.run( "hello" )
sleep( 0.1 )
end
term = { }
term = oldTerm
Lyqyd #2
Posted 19 February 2013 - 11:41 AM
Why in the hell are you running your coroutine in a for loop and not giving it events? A coroutine management loop is a while loop, and looks vaguely thus:


while true do
  event = {coroutine.yield()}
  coroutine.resume(myCoroutine, unpack(event))
end

Take a look at how the parallel API manages its coroutines. I guarantee you it isn't a for loop.
Exerro #3
Posted 19 February 2013 - 12:16 PM
yes this is nowhere near finished i was just testing how it behaved, the for loop is just because i have no way to terminate a while loop
my problem is the code not pausing at the os.pull event and stopping if i call sleep
Lyqyd #4
Posted 19 February 2013 - 12:59 PM
That's because your coroutine manager isn't behaving like it should. Fix the coroutine manager to do what it should, because that is why you are seeing the behavior you are. Your coroutine yields and then the manager resumes it a tenth of a second later, because that's exactly what you are telling it to do.
Exerro #5
Posted 19 February 2013 - 01:06 PM
ah so sleep doesnt sleep for how long you put in, it just yeilds then the coroutine is resumed straight after so it makes no difference?