systemc/process.lua

142 lines
2.9 KiB
Lua

local process = {}
function process.sleep(time)
time = time or 0
local t = os.startTimer(time)
local start = os.clock()
local ev, arg, tdiff
repeat
ev, arg = os.pullEvent()
tdiff = os.clock() - start
until (ev == "timer" and arg == t) or tdiff > time
end
process.signals = {
HALT = 0,
RESUME = 1,
TERM = 2,
KILL = 3
}
process.status = {
ALIVE = 0,
DEAD = 1,
HALTED = 2,
ERRORED = 3
}
process.processes = {}
local nextID = 0
function process.spawn(fn,err)
if err==_G.error then err = nil end
local thisID = nextID
nextID = nextID + 1
local proc = {
co = coroutine.create(fn),
err = err or function(e,p) error(e) end,
id = thisID,
status = process.status.ALIVE
}
process.processes[proc.id]=proc
process.tick(proc,{}) -- empty tick
return proc.id
end
function process.reset()
process.processes = {}
nextID = 0
end
function process.tick(proc,event)
if type(proc)~='table' then return false end
if proc.status ~= process.status.ALIVE then return false end
if proc.filter~=nil and proc.filter~=event[1] then
if event[1]~="terminate" then
return process.isRunning(proc.id)
end
end
local ok,err = coroutine.resume(proc.co,table.unpack(event))
if not ok then
proc.err(err,proc)
proc.status = process.status.DEAD
else
proc.filter = err
end
if coroutine.status(proc.co)=="dead" then
proc.status = process.status.DEAD
return false
end
return true
end
function process.get(id)
return process.processes[id]
end
function process.isRunning(id)
return process.get(id).status == process.status.ALIVE
end
function process.hasActive()
for i=0,(nextID-1) do
if process.get(i) and process.isRunning(i) then return true end
end
return false
end
function process.getActive()
ret = {}
for i=0,(nextID-1) do
if process.get(i) and process.isRunning(i) then table.insert(ret,i) end
end
return ret
end
local function apply_signal(proc,sig)
process.tick(proc,{"signal",sig})
if sig==process.signals.HALT and process.isRunning(proc.id) then
proc.status = process.status.HALTED
end
if sig==process.signals.RESUME and proc.status==process.status.HALTED then
proc.status = process.status.ALIVE
end
if sig==process.signals.TERM and process.isRunning(proc.id) then
process.tick(proc,{"terminate"})
end
if sig==process.signals.KILL and process.isRunning(proc.id) then
proc.status = process.status.DEAD
end
end
function process.signal(id,sig)
if type(sig)=="string" then sig = process.signals[sig] end
apply_signal(process.get(id),sig)
end
function process.killAll()
for i=0,(nextID-1) do
if process.get(i) then
process.signal(i,"TERM")
if process.isRunning(i) then process.signal(i,"KILL") end
end
end
end
for k,v in pairs(process.signals) do
process[string.lower(k)]=function(id) process.signal(id,v) end
end
function process.loop()
repeat
local event = {os.pullEvent()}
for i=0,(nextID-1) do
process.tick(process.get(i),event)
end
until not process.hasActive()
end
return process