107 lines
3.0 KiB
Lua
107 lines
3.0 KiB
Lua
local slicktable = require("slick.util.slicktable")
|
|
local util = require("slick.util.common")
|
|
|
|
--- @class slick.util.pool
|
|
--- @field type { new: function }
|
|
--- @field used table
|
|
--- @field free table
|
|
local pool = {}
|
|
local metatable = { __index = pool }
|
|
|
|
--- Constructs a new pool for the provided type.
|
|
--- @param poolType any
|
|
--- @return slick.util.pool
|
|
function pool.new(poolType)
|
|
return setmetatable({
|
|
type = poolType,
|
|
used = {},
|
|
free = {}
|
|
}, metatable)
|
|
end
|
|
|
|
--- Removes `value` from this pool's scope. `value` will not be re-used.
|
|
--- Only removing allocated (**not free!**) values is permitted. If `value` is in the free list,
|
|
--- this will fail and return false.
|
|
--- @param value any
|
|
--- @return boolean result true if `value` was removed from this pool, false otherwise
|
|
function pool:remove(value)
|
|
if self.used[value] then
|
|
self.used[value] = nil
|
|
return true
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
--- Adds `value` to this pool's scope. Behavior is undefined if `value` belongs to another pool.
|
|
--- If `value` is not exactly of the type this pool manages then it will not be added to this pool.
|
|
--- @param value any
|
|
--- @return boolean result true if `value` was added to this pool, false otherwise
|
|
function pool:add(value)
|
|
if util.is(value, self.type) then
|
|
self.used[value] = true
|
|
return true
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
--- Moves `value` from the source pool to the target pool.
|
|
--- This effective removes `value` from `source` and adds `value` to `target`
|
|
--- @param source slick.util.pool
|
|
--- @param target slick.util.pool
|
|
--- @param value any
|
|
--- @return boolean result true if `value` was moved successfully, `false` otherwise
|
|
--- @see slick.util.pool.add
|
|
--- @see slick.util.pool.remove
|
|
function pool.swap(source, target, value)
|
|
return source:remove(value) and target:add(value)
|
|
end
|
|
|
|
--- Allocates a new type, initializing the new instance with the provided arguments.
|
|
--- @param ... any arguments to pass to the new instance
|
|
--- @return any
|
|
function pool:allocate(...)
|
|
local result
|
|
if #self.free == 0 then
|
|
result = self.type and self.type.new() or {}
|
|
if self.type then
|
|
result:init(...)
|
|
end
|
|
|
|
self.used[result] = true
|
|
else
|
|
result = table.remove(self.free, #self.free)
|
|
if self.type then
|
|
result:init(...)
|
|
end
|
|
|
|
self.used[result] = true
|
|
end
|
|
return result
|
|
end
|
|
|
|
--- Returns an instance to the pool.
|
|
--- @param t any the type to return to the pool
|
|
function pool:deallocate(t)
|
|
self.used[t] = nil
|
|
table.insert(self.free, t)
|
|
end
|
|
|
|
--- Moves all used instances to the free instance list.
|
|
--- Anything returned by allocate is no longer considered valid - the instance may be reused.
|
|
--- @see slick.util.pool.allocate
|
|
function pool:reset()
|
|
for v in pairs(self.used) do
|
|
self:deallocate(v)
|
|
end
|
|
end
|
|
|
|
--- Clears all tracking for free and used instances.
|
|
function pool:clear()
|
|
slicktable.clear(self.used)
|
|
slicktable.clear(self.free)
|
|
end
|
|
|
|
return pool
|