mirror of
https://github.com/kepler155c/opus
synced 2024-12-28 01:20:27 +00:00
122 lines
2.5 KiB
Lua
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
|