You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 lines
5.1 KiB
Lua

local setmetatable = setmetatable
local pairs = pairs
---
---Table pool for lua
---
---@class Pool
---@field public DEFAULT_TAG string @default object tag for pool
---@field private _ctorHandle table<string, function>
---@field private _pools table<string, table[]>
local Pool = {}
local DEFAULT_TAG = "__"
Pool.DEFAULT_TAG = DEFAULT_TAG
Pool.__index = Pool
setmetatable(
Pool,
{
__call = function(class, opt)
local instance = {}
setmetatable(instance, Pool)
instance:new(opt)
return instance
end
}
)
---@param pool Pool
---@param tag string
---@param create boolean
local function getPoolArr(pool, tag, create)
local poolArr = pool._pools[tag]
if not poolArr and create then
poolArr = {}
pool._pools[tag] = poolArr
end
return poolArr
end
---@param pool Pool
---@param tag string
local function createInstance(pool, tag)
tag = tag or DEFAULT_TAG
local ctorHandle = pool._ctorHandle[tag]
if ctorHandle then
return ctorHandle()
else
return {}
end
end
---@param pool Pool
---@param tag string
---@vararg any
local function getFromPool(pool, tag, ...)
local ins = nil
if pool._pools[tag] then
local poolArr = pool._pools[tag]
if #poolArr > 0 then
ins = poolArr[#poolArr]
poolArr[#poolArr] = nil
end
end
if not ins then
ins = createInstance(pool, tag)
end
if ins.awakeFromPool then
ins:awakeFromPool(...)
end
return ins
end
---@param pool Pool
---@param tag string
---@param t string
---@vararg any
local function recycleToPool(pool, tag, t, ...)
local poolArr = getPoolArr(pool, tag, true)
poolArr[#poolArr + 1] = t
if t.recycleToPool then
t:recycleToPool(...)
end
end
---@param pool Pool
---@param tag string
---@param clearCtorHandle boolean
local function clearPool(pool, tag, clearCtorHandle)
pool._pools[tag] = nil
if clearCtorHandle then
pool._ctorHandle[tag] = nil
end
end
---@private
function Pool:new(opt)
self._ctorHandle = {}
self._pools = {}
if opt then
if opt.ctor then
for k, v in pairs(opt.ctor) do
self._ctorHandle[k] = v
end
end
if opt.presize then
for k, v in pairs(opt.presize) do
self:presize(v, k)
end
end
end
end
---
---Set table constructor handle for object
---when get a table from pool, if there isn't a table in pool,
---will use this constructor handle to create new one and return it.
---@public
---@param handle function @create object handle
---@param tag string @[option] object tag
function Pool:setCtorHandle(handle, tag)
tag = tag or DEFAULT_TAG
self._ctorHandle[tag] = handle
end
---
---Get table from pool
---if table has a awakeFromPool function,
---will call this function with parameters by pass.
---@public
---@vararg any
---@return table
function Pool:get(...)
return getFromPool(self, DEFAULT_TAG, ...)
end
---
---Get table from pool with object tag
---if table has a awakeFromPool function,
---will call taht function with parameters by pass.
---@public
---@param tag string
---@vararg any
---@return table
function Pool:getWithTag(tag, ...)
return getFromPool(self, tag, ...)
end
---
---Recycle table to pool
---if table has a recycleToPool function,
---will call that function with parameters by pass.
---@public
---@param t table
---@vararg any
function Pool:recycle(t, ...)
recycleToPool(self, DEFAULT_TAG, t, ...)
end
---
---Recycle table to pool with object tag
---if table has a recycleToPool function,
---will call that function with parameters by pass.
---@public
---@param t table
---@param tag string
---@vararg any
function Pool:recycleWithTag(t, tag, ...)
recycleToPool(self, tag, t, ...)
end
---
---Pre create some table with an option object tag.
---@public
---@param count number
---@param tag string @[option] object tag
---@return boolean
function Pool:presize(count, tag)
local poolArr = getPoolArr(self, tag or DEFAULT_TAG, true)
if #poolArr >= count then
return false
end
local needCreateSize = count - #poolArr
local ctorHandle = self._ctorHandle[tag]
local createFunction = ctorHandle and function()
return ctorHandle()
end or function()
return {}
end
for _ = 1, needCreateSize do
poolArr[#poolArr + 1] = createFunction()
end
return true
end
---
---Clear objects in pool
---@public
---@param clearCtorHandle boolean @default false
function Pool:clear(clearCtorHandle)
clearCtorHandle = clearCtorHandle or false
clearPool(self, DEFAULT_TAG, clearCtorHandle)
end
---
---Clear all objects in pool
---@public
---@param clearCtorHandle boolean @default false
function Pool:clearAll(_)
self._pools = {}
self._ctorHandle = {}
end
---
---Clear all objects with an object tag in pool
---@public
---@param tag string
---@param clearCtorHandle boolean @default false
function Pool:clearTag(tag, clearCtorHandle)
clearCtorHandle = clearCtorHandle or false
clearPool(self, tag, clearCtorHandle)
end
return Pool