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

Multi-tasking

Started by logsys, 15 July 2014 - 10:19 AM
logsys #1
Posted 15 July 2014 - 12:19 PM
Lately, I have been trying to implement multitasking into my OS, but no success at all.. My problem is, how do I terminate a coroutine and how do I run multiple coroutines? As far as I could tell, a coroutine gets into a "standby" mode when that coroutine runs another. Can someone do a detailed tutorial for me? I always get confused with it
flaghacker #2
Posted 15 July 2014 - 01:05 PM
This is a tutorial from the tutorials page on the forum, if that's not in-depth enough then yea…
You could also have a look at the online PIL.
logsys #3
Posted 15 July 2014 - 09:46 PM
kinda left me confused, but im getting the handle of it.. now how do I kill a coroutine? like my program doesnt have coroutine.yield neither it ended and I want to kill it
flaghacker #4
Posted 15 July 2014 - 11:04 PM
I think you misunderstand coroutines.

Coroutines are a way to run a function, save its state, give it it's own events, and resume it later. The "own events" means that every coroutine gets its own copy of all the events.

You are probably asking for "How can the parent program terminate one of its coroutines?". That's impossible.

Let's think of a program that uses "sleep" somewhere. After the program has called the sleep function, that program pauses until the sleep ends (returns). There's no way for the program to stop that sleep. It's the same with coroutines, specifically with coroutine.resume.



Remember, os.pullEvent and functions that use os.pullEvent like sleep, read, turtle movement, slowprint, … ALL YIELD. If there's no such function in your program it will error: "to long without yielding", so there's probably one in your coroutine.
Edited on 15 July 2014 - 09:08 PM
oeed #5
Posted 16 July 2014 - 12:32 AM
It's also worth noting that Lua can only do one thing at once. There's no multithreading, parallel makes it look like there is, but there isn't.

The best way in my opinion is to look at APIs or OSs that have the functionality that you want.
flaghacker #6
Posted 16 July 2014 - 09:11 AM
It's also worth noting that Lua can only do one thing at once. There's no multithreading, parallel makes it look like there is, but there isn't.

The best way in my opinion is to look at APIs or OSs that have the functionality that you want.

Isn't that also a property of CPU's itself? That just goes so fast you can't notice it. Or isn't that the case anymore with modern CPU's?
Bomb Bloke #7
Posted 16 July 2014 - 09:26 AM
Modern CPUs generally have multiple physical cores - for example, a basic 3ghz dual-core system has two cores, each of which can run instructions at a rate of up to 3ghz. By spreading the load between them, they can literally process instructions in true parallel.

You might remember about ten years ago (and earlier), where if a program on your computer went haywire, it'd chew up all your system resources - meaning that the computer struggled just to get the task manager open so you could terminate the problematic process.

All that mostly went away with the rise of multi-core CPUs. This is because most programmers don't bother to write multi-threaded code, so their programs can only run on one core at a time - meaning that even if their code DOES go haywire, the other core is still free to do whatever else it is the user wants to do. In short, these CPUs are great for running multiple processor-intensive programs at the same time, but for the average user you'll never really want more than a dual.

A negative side effect is that users don't know there's a problem when a program suddenly decides to "consume" a core. Or rather, they maybe notice that the system's heating up and running its fans flat out, but since performance isn't affected they don't care.
oeed #8
Posted 16 July 2014 - 09:26 AM
It's also worth noting that Lua can only do one thing at once. There's no multithreading, parallel makes it look like there is, but there isn't.

The best way in my opinion is to look at APIs or OSs that have the functionality that you want.

Isn't that also a property of CPU's itself? That just goes so fast you can't notice it. Or isn't that the case anymore with modern CPU's?
Well, multithreading's not really the correct term, but it's important to know that Lua is single threaded/what ever you want to call it. When I first started playing around with CC I didn't realise this and as a result made lots of poor design decisions.
logsys #9
Posted 17 July 2014 - 07:36 PM
ok, so what ive seen from that is that coroutines cant be killed. In an normal program, without OSes, it returns "Terminated" when CTRL+T is pressed, but in normal programs they yield even if for a bit? If yes, how can I prevent it from resuming? if the program yields, in a sleep or something, will my program resumes? if yes, can I simply make it disapear with a process = nil?
Edited on 17 July 2014 - 05:36 PM
theoriginalbit #10
Posted 17 July 2014 - 07:50 PM
Assuming you're implementing coroutines yourself and not using the parallel api; yes, once the running program yields, control will fall back to your program, in turn you must yield, and then when you resume the program you must provide it with the event data you received (taking into consideration it's filter if it has one). As for the killing coroutines, it isn't possible. Simply remove the reference — for example routine = nil — and it will remain in a suspended status until the garbage collector comes through and destroys it (which in Minecraft is every game loop *shudders*).

I really suggest that you have a read through Bubba's# coroutine tutorial if you haven't already. As well as taking a look at how the Parallel API works.

# a.k.a. AliquotMesozoic and ChallengeMe
logsys #11
Posted 17 July 2014 - 09:32 PM
Thank you all for your support! +1 for all of you!
logsys #12
Posted 18 July 2014 - 03:07 PM
As this is still open.. I will post here a question.. im since 4 hours trying to solve this error.. I have this code(code 1) to manage the coroutines.. It has worked fine when I used the code 2 that is similar to that one.. When I try to open my file browser inside LogOS, doesnt do anything.. and if I terminate with CTRL+T or the T button on the ccemuredux, it errors inside the program.. I hope you guys have time to debug my code and help me finding the error. I tried outside the OS, but it went far badly..

Here are the codes:
Code 1

function createProc(dir)
proc = {}
proc.name = fs.getName(dir)
proc.coroutine = coroutine.create(loadfile(dir))
return proc
end
function runProc(proc)
local function terminateProc(proc)
  proc = nil
  term.redirect(term.native())
  nWindow.setVisible(false)
  nWindow = nil
end
x,y = term.getSize()
nWindow = window.create(term.native(),1,2,x,y-1,true)
term.redirect(nWindow)
sFilter, arg1 = coroutine.resume(proc.coroutine)
while true do
  if coroutine.status(proc.coroutine) == "dead" then
   if not sFilter then term.setBackgroundColor(colors.black) print(arg1) sleep(1.2) end
   terminateProc(proc)
   break
  end

  local eventData = { os.pullEventRaw( sFilter ) }
	 if eventData[1] == "terminate" then
		 terminateProc(proc)
		 break
	 end
	 if eventData[1] == "mouse_click" and eventData[4] == "-1" then terminateProc(proc) break end
  event, arg1 = coroutine.resume(proc.coroutine, unpack(eventData))
end
return nil
end
Code 2

function tester()
  while true do
	print(os.time() .. " -- Running")
	coroutine.yield("mouse_click")
	print(os.time() .. " -- Resumed")
  end
end

coroutineA = coroutine.create(tester)
print("Preparing to resume coroutine....")
coroutine.resume(coroutineA)
while true do
  arg1, arg2, arg3, arg4, arg5, arg6 = coroutine.yield(arg1)
  if arg1 == "mouse_click" then
	if arg4 == 1 then
	  --terminate
	  coroutineA = nil
	  print("Terminated")
	  break
	else
	  coroutine.resume(coroutineA,arg1,arg2,arg3,arg4,arg5,arg6)
	end
  else
	coroutine.resume(coroutineA, arg1, arg2, arg3, arg4, arg5, arg6)
  end
end
logsys #13
Posted 18 July 2014 - 04:33 PM
As this is still open.. I will post here a question.. im since 4 hours trying to solve this error.. I have this code(code 1) to manage the coroutines.. It has worked fine when I used the code 2 that is similar to that one.. When I try to open my file browser inside LogOS, doesnt do anything.. and if I terminate with CTRL+T or the T button on the ccemuredux, it errors inside the program.. I hope you guys have time to debug my code and help me finding the error. I tried outside the OS, but it went far badly..

Here are the codes:
Code 1

function createProc(dir)
proc = {}
proc.name = fs.getName(dir)
proc.coroutine = coroutine.create(loadfile(dir))
return proc
end
function runProc(proc)
local function terminateProc(proc)
  proc = nil
  term.redirect(term.native())
  nWindow.setVisible(false)
  nWindow = nil
end
x,y = term.getSize()
nWindow = window.create(term.native(),1,2,x,y-1,true)
term.redirect(nWindow)
sFilter, arg1 = coroutine.resume(proc.coroutine)
while true do
  if coroutine.status(proc.coroutine) == "dead" then
   if not sFilter then term.setBackgroundColor(colors.black) print(arg1) sleep(1.2) end
   terminateProc(proc)
   break
  end

  local eventData = { os.pullEventRaw( sFilter ) }
	 if eventData[1] == "terminate" then
		 terminateProc(proc)
		 break
	 end
	 if eventData[1] == "mouse_click" and eventData[4] == "-1" then terminateProc(proc) break end
  [s]event[/s] [b]sFilter[/b], arg1 = coroutine.resume(proc.coroutine, unpack(eventData))
end
return nil
end
Code 2

function tester()
  while true do
	print(os.time() .. " -- Running")
	coroutine.yield("mouse_click")
	print(os.time() .. " -- Resumed")
  end
end

coroutineA = coroutine.create(tester)
print("Preparing to resume coroutine....")
coroutine.resume(coroutineA)
while true do
  arg1, arg2, arg3, arg4, arg5, arg6 = coroutine.yield(arg1)
  if arg1 == "mouse_click" then
	if arg4 == 1 then
	  --terminate
	  coroutineA = nil
	  print("Terminated")
	  break
	else
	  coroutine.resume(coroutineA,arg1,arg2,arg3,arg4,arg5,arg6)
	end
  else
	coroutine.resume(coroutineA, arg1, arg2, arg3, arg4, arg5, arg6)
  end
end
Fixed that bit of code in Code 1 and the program stopped erroring… but still doesn't respond to pull events.. I already tried os.pullEvent os.pullEventRaw and coroutine.yield.. no good until now