1
0
mirror of https://github.com/kepler155c/opus synced 2024-11-05 08:26:16 +00:00
opus/sys/apis/process.lua
kepler155c@gmail.com aba2ae31ea threads
2016-12-27 16:06:30 -05:00

122 lines
2.5 KiB
Lua

local Util = require('util')
local Process = { }
function Process:init(args)
self.args = { }
self.uid = 0
self.threads = { }
Util.merge(self, args)
self.name = self.name or 'Thread:' .. self.uid
end
function Process:isDead()
return coroutine.status(self.co) == 'dead'
end
function Process:terminate()
print('terminating ' .. self.name)
self:resume('terminate')
end
function Process:threadEvent(...)
for _,key in pairs(Util.keys(self.threads)) do
local thread = self.threads[key]
if thread then
thread:resume(...)
end
end
end
function Process:addThread(fn, ...)
return self:newThread(nil, fn, ...)
end
-- deprecated
function Process:newThread(name, fn, ...)
self.uid = self.uid + 1
local thread = { }
setmetatable(thread, { __index = Process })
thread:init({
fn = fn,
name = name,
uid = self.uid,
})
local args = { ... }
thread.co = coroutine.create(function()
local s, m = pcall(function() fn(unpack(args)) end)
if not s and m then
if m == 'Terminated' then
--printError(thread.name .. ' terminated')
else
printError(m)
end
end
--print('thread died ' .. thread.name)
self.threads[thread.uid] = nil
thread:threadEvent('terminate')
return s, m
end)
self.threads[thread.uid] = thread
thread:resume()
return thread
end
function Process:resume(event, ...)
-- threads get a chance to process the event regardless of the main process filter
self:threadEvent(event, ...)
if not self.filter or self.filter == event or event == "terminate" then
local ok, result = coroutine.resume(self.co, event, ...)
if ok then
self.filter = result
end
return ok, result
end
return true, self.filter
end
-- confusing...
-- pull either one event if no filter or until event matches filter
-- or until terminated (regardless of filter)
function Process:pullEvent(filter)
while true do
local e = { os.pullEventRaw() }
self:threadEvent(unpack(e))
if not filter or e[1] == filter or e[1] == 'terminate' then
return unpack(e)
end
end
end
-- pull events until either the filter is matched or terminated
function Process:pullEvents(filter)
while true do
local e = { os.pullEventRaw() }
self:threadEvent(unpack(e))
if (filter and e[1] == filter) or e[1] == 'terminate' then
return unpack(e)
end
end
end
local process = { }
setmetatable(process, { __index = Process })
process:init({ name = 'Main', co = coroutine.running() })
return process