2021-01-24 04:53:14 +00:00
|
|
|
local mt = {}
|
|
|
|
|
|
|
|
mt.newPool = function()
|
|
|
|
local pool = {}
|
2021-01-30 14:14:11 +00:00
|
|
|
pool.threads = {} -- indexed by coroutines, contains their metadata
|
|
|
|
pool.namedThreads = {} -- indexed by coroutine names, contains their metadata also.
|
|
|
|
-- coroutines are named if their metadata has a name field.
|
|
|
|
pool.threadcount = 0 -- used for detecting when all things in a pool are depleted
|
2021-01-24 04:53:14 +00:00
|
|
|
|
|
|
|
pool.clear = function()
|
|
|
|
pool.threads = {}
|
2021-01-24 06:17:58 +00:00
|
|
|
pool.namedThreads = {}
|
|
|
|
pool.threadcount = 0
|
2021-01-24 04:53:14 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
pool.add = function(fn, options)
|
|
|
|
options = options or {}
|
|
|
|
options.co = coroutine.create(fn)
|
|
|
|
pool.threads[options.co] = options
|
2021-01-24 06:17:58 +00:00
|
|
|
if options.name then
|
|
|
|
pool.namedThreads[options.name] = options
|
|
|
|
end
|
2021-01-24 04:53:14 +00:00
|
|
|
pool.threadcount = pool.threadcount + 1
|
|
|
|
os.queueEvent("pool_fn_added",options,pool)
|
2021-01-24 06:17:58 +00:00
|
|
|
return options.co
|
|
|
|
end
|
|
|
|
|
|
|
|
pool.rm = function(name)
|
|
|
|
if not pool.namedThreads[name] then
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
pool.threads[pool.namedThreads[name].co] = nil
|
|
|
|
pool.namedThreads[name] = nil
|
|
|
|
pool.threadcount = pool.threadcount - 1
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
pool.addFile = function(filename, options)
|
|
|
|
pool.add(function()
|
|
|
|
dofile(filename)
|
|
|
|
end,options)
|
2021-01-24 04:53:14 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
pool.run = function(terminable)
|
|
|
|
terminable = terminable or true -- if false, terminate events will be echoed to coroutines instead of
|
|
|
|
-- terminating this pool
|
|
|
|
while true do
|
|
|
|
local event = {coroutine.yield()}
|
|
|
|
if event[1] == "terminate" and terminable then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
for thread, options in pairs(pool.threads) do
|
|
|
|
if coroutine.status(thread) ~= "dead" then
|
|
|
|
if event[1] == options.filter or options.filter == nil then
|
|
|
|
local x,e,y = pcall(coroutine.resume,thread,unpack(event))
|
|
|
|
options.filter = y
|
|
|
|
if not x then
|
|
|
|
os.queueEvent("pool_fn_crash",e,options,pool)
|
|
|
|
pool.threadcount = pool.threadcount - 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
os.queueEvent("pool_fn_end",options,pool)
|
|
|
|
pool.threadcount = pool.threadcount - 1
|
|
|
|
pool.threads[thread] = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if pool.threadcount == 0 then return end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return pool
|
|
|
|
end
|
|
|
|
|
|
|
|
return mt
|