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

Starting and cancelling tasks away from main thread

Started by ShadowDisruptor, 12 August 2015 - 03:28 PM
ShadowDisruptor #1
Posted 12 August 2015 - 05:28 PM
Hello. I am working on a graphical HUD using OpenPeripherals (Don't worry, this is just to give info) Basically, different players will have different screens doing different things (one persons could be showing time, others how many pigs are in a 5ft radius) My graphics for this are going to have animations, which starts to cause a problem when we want to serve other players.

How can I make it so that 1 function won't freeze, for say, a while loop running in the program, and how can I have multiple of these functions, so that when I use animations it doesn't freeze the stat updates and commands for other players?
metron80 #2
Posted 12 August 2015 - 05:55 PM
You may want to look in to the parallel API. Using that, you should be able to run multiple functions at once.
Exerro #3
Posted 12 August 2015 - 06:22 PM
While that is what the parallel API is for, I'd suggest taking a closer look at coroutines or the various multitasking APIs on these forums. Parallel only really works when you have a list of static functions: you can't stop, pause, resume, or change existing functions, and there's no way to add new ones.

However, this is entirely avoidable using a system of timers, assuming you write all of the source code and don't yield (or sleep) anywhere. By using os.startTimer(), you can trigger a 'timer' event after a certain time has passed. The second argument of the event is some random number ID, and is returned by os.startTimer() when you queue it. By using this number, you can work out what the timer is for and act accordingly.
ShadowDisruptor #4
Posted 12 August 2015 - 06:47 PM
While that is what the parallel API is for, I'd suggest taking a closer look at coroutines or the various multitasking APIs on these forums. Parallel only really works when you have a list of static functions: you can't stop, pause, resume, or change existing functions, and there's no way to add new ones.

However, this is entirely avoidable using a system of timers, assuming you write all of the source code and don't yield (or sleep) anywhere. By using os.startTimer(), you can trigger a 'timer' event after a certain time has passed. The second argument of the event is some random number ID, and is returned by os.startTimer() when you queue it. By using this number, you can work out what the timer is for and act accordingly.

Thanks, coroutines should work. The timers are a good idea, but since I'm working with animated graphics I'd need to save a huge amount of values to animate without sleeping
MKlegoman357 #5
Posted 12 August 2015 - 06:50 PM
It's not like you're going to have millions of animations running at the same time. Using tables and an OOP approach you could deal with this quite easily. IMO, there will be 2-3 animations at most happening at the same time anyways. Also, using timers, rather than coroutines will actually make your program run faster and smoother.
Edited on 12 August 2015 - 04:51 PM
Exerro #6
Posted 12 August 2015 - 09:22 PM
Yeah, coroutines are very slow. If you're worried about creating lots of timers, don't. Sleep creates a timer anyway, so using sleep won't make any less timers than using your own timer manager, and you can also go about reusing timers if you do it yourself. What do I mean by this? Well, if two things call startTimer(.5), only one timer event is queued, but the action of both is called when the timer times out. An example of this is the code below:

Spoiler

local function updateTimers( timer )
for i = #timers, 1, -1 do
  if timers[i].timer == timer then
   for h = 1, #timers[i] do
	timers[i][h]()
   end
   table.remove( timers, i )
  end
end
end
local function newTimer( n, handler )
local timeout = os.clock() + n
local t
for i = 1, #timers do
  if timers[i].timeout == timeout then
   t = timers[i]
   break
  end
end
if not t then
  t = { timeout = timeout, timer = os.startTimer( n ) }
  timers[#timers + 1] = t
end
t[#t + 1] = handler
end

Excuse the fact that it is crudely cut out of something else I made a while ago.
Edited on 12 August 2015 - 07:24 PM
Bomb Bloke #7
Posted 13 August 2015 - 01:33 AM
Yeah, coroutines are very slow.

Eh? What gave you that idea?
Exerro #8
Posted 13 August 2015 - 02:23 PM
Yeah, coroutines are very slow.

Eh? What gave you that idea?
Compared to a table of timers, that is.