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

Review for my process manager code

Started by thecrimulo, 19 September 2016 - 06:02 PM
thecrimulo #1
Posted 19 September 2016 - 08:02 PM
So, I've asked how to make a TLCO, from scratch, in a library, and I just need someone to review if my code is correct.

--[[
mnx-sr12 : Moonux Satellite Rewrite 12
Made by thecrimulo
NAME:	    /lib/thread.l
CATEGORY:    library
SET:		 Native Libraries RW12
VERSION:	 12:alpha0
DESCRIPTION:
  This library is loaded first and used on
  the thread manager (/vit/mgr/thread.mgr)
]]--
local thread = {}
local started = {}
local running = {}
local last_uid = 0
function thread.new(task, file, uid)
uid = uid or last_uid + 1
last_uid = last_uid + 1
local self = {}
self.uid = uid
self.task = task
self.thread = coroutine.create(task)
self.file = file
self.filter = nil
self.error = nil
self.dead = false
self.status = "suspended"
self.queue = {}
self.resume = function(...)
  local fst = ...
  if self.filter == nil or fst == self.filter then
   ok, err = coroutine.resume(self.thread, ...)
   if ok then
    self.filter = err
    self.status = coroutine.status(self.thread)
    if self.status == "dead" then self.dead = true end
   else
    self.status = coroutine.status(self.thread)
    if self.status == "dead" then self.dead = true end
    return err
   end
  end
end
started[self.uid] = self
return self
end
function thread.queue(process, event, parameters)
process.queue[#process.queue+1] = {['event'] = event, ['parameters'] = parameters}
return true
end

function thread.kill(process)
process.dead = true
process.status = "dead"
thread.queue(process, "sig:terminate", {})
end
function thread.killAll(tasklist)
if not STATE_SHUTDOWN or not STATE_RESTART then return false end
for uid, task in pairs(tasklist) do
   thread.kill(task)
end
end
function thread.runAll(tasklist)
evt = {}
while true do
  evt = {os.pullEvent()}
  for uid, task in pairs(tasklist) do
   if not task.dead then
    task.resume(unpack(event))
   end
  end
end
end
Thanks in advance
~ Dael
Sewbacca #2
Posted 19 September 2016 - 09:14 PM
1. process.queue[#process.queue+1] = {['event'] = event, ['parameters'] = parameters}
have to be
process.queue[#process.queue+1] = {[event] = event, [parameters] = parameters}
2. I am not sure, what does self.file = file
3. I think you get an error if someone do
Thread.new(<…>)
Thread.new(<firstArg, secondArg>, 1)
4. I am not sure, where STATE_SHUTDOWN and STATE_RESTART are declared
5. The rest should work

Sewbacca
thecrimulo #3
Posted 19 September 2016 - 10:26 PM
1. process.queue[#process.queue+1] = {['event'] = event, ['parameters'] = parameters}
have to be
process.queue[#process.queue+1] = {[event] = event, [parameters] = parameters}
2. I am not sure, what does self.file = file
3. I think you get an error if someone do
Thread.new(<…>)
Thread.new(<firstArg, secondArg>, 1)
4. I am not sure, where STATE_SHUTDOWN and STATE_RESTART are declared
5. The rest should work

Sewbacca
1. If I am making a key, with that name to be called, I need the quotes, I don't want to set the key to the value of those variables
2. self.file is the file that the function for the coroutine is loading from (loadfile)
3. Can you specify, please?
4. STATE_SHUTDOWN and STATE_RESTART are declared in /lib/os.l (The OS library, that manages restarts, shutdowns and power-ons)
5. Thanks
Sewbacca #4
Posted 20 September 2016 - 10:48 AM
1. Okay but why you don't just write:
process.queue[#process.queue+1] = {event = event, parameters = parameters}
It is easier, but it is matter of taste
2. Why do you need self.file?
3. Yes
first uid = 1
and
second uid = 1 too, I think it isn't expected
4. If native os.shutdown and os.restart are called, the computer shuts down directly, did you handled this?
Bomb Bloke #5
Posted 20 September 2016 - 01:44 PM
Assuming regular CC scripts are being loaded into tasklist, self.filter should be ignored if fst == "terminate". Though I'm not sure if you want to pass events relating to user input to more than one coroutine per iteration…

Is your process.queue() stuff a work-in-progress? I see you have a means to put stuff in there, but nothing to actually use that stuff once it's in place…

Otherwise I'm not seeing any obvious issues.

But, to nit-pick, if you created a consecutively indexed table of processes and indexed through that in reverse you'd be able to simply remove dead entries from further iterations instead of leaving them in there as clutter. Eg:

function thread.runAll(tasklist)
	local tasks = {}
	
	for uid, task in pairs(tasklist) do tasks[#tasks + 1] = task end
	
	while #tasks > 0 do
		local evt = {os.pullEvent()}

		for i = #tasks, 1, -1 do
			local thisTask = task[i]
			
			if thisTask.dead then
				table.remove(tasks, i)
			else
				thisTask.resume(unpack(event))
			end
		end
	end
end
thecrimulo #6
Posted 20 September 2016 - 08:11 PM
1. Okay but why you don't just write:
process.queue[#process.queue+1] = {event = event, parameters = parameters}
It is easier, but it is matter of taste
2. Why do you need self.file?
3. Yes
first uid = 1
and
second uid = 1 too, I think it isn't expected
4. If native os.shutdown and os.restart are called, the computer shuts down directly, did you handled this?
2. Process listing, file that the function was loaded from, I am planning to include it in the info
3. Thanks, ill fix it
4. Yes, I did. But it is in another file I have to update. tho os.forceoff() will force shutdown.

Assuming regular CC scripts are being loaded into tasklist, self.filter should be ignored if fst == "terminate". Though I'm not sure if you want to pass events relating to user input to more than one coroutine per iteration…

Is your process.queue() stuff a work-in-progress? I see you have a means to put stuff in there, but nothing to actually use that stuff once it's in place…

Otherwise I'm not seeing any obvious issues.

But, to nit-pick, if you created a consecutively indexed table of processes and indexed through that in reverse you'd be able to simply remove dead entries from further iterations instead of leaving them in there as clutter. Eg:

function thread.runAll(tasklist)
	local tasks = {}
	
	for uid, task in pairs(tasklist) do tasks[#tasks + 1] = task end
	
	while #tasks > 0 do
		local evt = {os.pullEvent()}

		for i = #tasks, 1, -1 do
			local thisTask = task[i]
			
			if thisTask.dead then
				table.remove(tasks, i)
			else
				thisTask.resume(unpack(event))
			end
		end
	end
end
I am not really sure of the first thing, but I'll review it
About process.queue, I plan to do some kind of multi-file data sharing, own events or variables
Thanks about the tip.