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

Multithreading, as a library

Started by thecrimulo, 16 September 2016 - 04:50 PM
thecrimulo #1
Posted 16 September 2016 - 06:50 PM
Hello there,
So, I've been reading the coroutine tutorial, and I think I get it.
The problem is that, in the tutorials, the maximum I get to is to switch between two functions. My problem comes
when it gets to making it a library, not an executing script. I need to start a thread, run them all in a while true loop,
as all programs will run in there, but I don't really know how to make it. Also killing the processes in some kind
of SIGKILL and SIGTERM. Also, my programs will need IDs, parents and childs, and I tried to use CCDelta's Thread.lua or trying to look at cubix's proc_manager but I don't get myself clear with all of this. So, I have various questions on this topic:

1) How events internally work, if they use yields and resumes?
2) How do I implement multithreading as a simple and clean library with the things mentioned above?
3) How can I make it so all processes must run on that and when there are no processes, shut down?

Thanks in advance
~ Dael
KingofGamesYami #2
Posted 16 September 2016 - 07:10 PM
1) Yay, events. I made an awesome graphic on how they work.

2) Multithreading is impossible in lua, as coroutines do not run at the same time. Rather, they take turns running. In fact, all the computers in a world run on a single thread - if one of them is executing code, all the others are not.
However, I would look at multishell as an example.

3) It sounds like you're after a Top Level Coroutine Override (there are a few on the forums). Essentially, crash rednet and multishell then run everything through your task manager.

I would highly recommend reading this tutorial.
Sewbacca #3
Posted 16 September 2016 - 07:54 PM
1) Yay, events. I made an awesome graphic on how they work.

First, very good work KingofGamesYami! :)/>

2. Yes, multi threading is possible in Lua, but like KingofGamesYami mentioned, multi threading isn't possible.
The problem is that a single processor core can run just one thread at one time and LuaJ works like a single processor core.
To implement multi threading, you have to switch very fast between multiple threads (That was used on single core systems to implement a kind of multi threading):
thread1| then
thread2| then
thread3| then from beginning.
Every time, when an thread run sleep/textutils.slowPrint/os.pullEvent/…
the program waits for an event with calling coroutine.yield.
The program fall asleep and give the control to the coroutine manager, who call the next coroutine and so on (see awesome graphic).
After running through a table of coroutines, the manager waits for an event. Sleep for example run os.startTimer(nTime) to queue an event at time: (now + nTime) into the global computer queue.
After this time, the coroutine control manager get the event:
'timer', 855426.
The control manager resolves the coroutine who need a timer event (see awesome graphic) and resumes the coroutine with the event.
os.startTimer returns a number handle, to identify your timer, because many parallel working programs need a timer event.
Sleep clipped his handle 855426 into a variable and got his event.
First, sleep check out, if the event is a timer event and not a terminate event (see awesome graphic).
Then he identify the timer:

local nHandle = os.startTimer(nTimeout)
local sEvent, nTimer;
repeat
   sEvent, nTimer = coroutine.yield('timer')
until sEvent == 'timer' and nTimer == nHandle
If all work, sleep give the control to the upper (function) caller.
The upper caller calls coroutine.yield and see awesome graphic.

In short: The program says yield, and the coroutine control manager runs the next coroutine.
In realy short: see awesome graphic.

Good work KingofGamesYami :)/>

And last but not the least:
3.

while true do
  <coroutine managing>
end
term.setCursorBlink(false)
term.setTextColor(colors.white)
term.setBackgroundColor(colors.black)
term.clear()
term.setCursorPos(1, 1)
print('No more processes on the stack')
write('Press any key to shutdown')
term.setCursorBlink(true)
coroutine.yield('key')
os.shutodown()

Sewbacca :)/>
Edited on 16 September 2016 - 05:59 PM
Bomb Bloke #4
Posted 17 September 2016 - 01:50 AM
1) How events internally work, if they use yields and resumes?

Basically "events" are just what we call the data ComputerCraft uses to resume our computer's coroutines with. They're only ever resumed when "something happens".

In fact, all the computers in a world run on a single thread - if one of them is executing code, all the others are not.

Well, truth be told they do each get their own thread, but it's still the case that everything runs synchronously.

However, I would look at multishell as an example.

Seconded, the only feature it lacks is the ability to kill specific processes (though it'd be trivial for anyone to add such functionality to the main script file).

Just to elaborate on what that source is about, as of CC 1.6 multishell is loaded on boot by any advanced system. It defaults to running a single coroutine with the regular CraftOS shell in it, but provides API functions allowing additional "tabs" to be opened with further shell instances.

http://www.computercraft.info/wiki/Multishell
http://www.computercraft.info/wiki/Multishell_%28API%29