195 lines
5.1 KiB
Lua
195 lines
5.1 KiB
Lua
local insert = table.insert
|
|
local remove = table.remove
|
|
|
|
local classic = require("lib.classic.classic")
|
|
|
|
|
|
---@class Pool : lib.classic.class
|
|
---@field private fn function
|
|
---@field private rfn function
|
|
---@field private efn function
|
|
---@field active any[]
|
|
---@field hidden any[]
|
|
---@field max number | nil
|
|
---@field name string
|
|
local pool = classic:extend()
|
|
pool._VERSION = "0.0.0-alpha"
|
|
pool._DESCRIPTION = "A simple and straightforward pool made for LÖVE."
|
|
pool._URL = "https://github.com/FNicon/reoof"
|
|
pool._LICENSE = [[
|
|
MIT License
|
|
|
|
Copyright (c) 2025 FNicon
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
]]
|
|
|
|
--- default equal function
|
|
---@param v1 any
|
|
---@param v2 any
|
|
local function defaultEqual(v1, v2)
|
|
return v1 == v2
|
|
end
|
|
|
|
--- Return the first index with the given value (or nil if not found).
|
|
---@param array any[]
|
|
---@param value any
|
|
---@param efn fun(...):boolean
|
|
---@return number?
|
|
local function indexOf(array, value, efn)
|
|
for i, v in pairs(array) do
|
|
if efn(v, value) then
|
|
return i
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
--- initialize pool
|
|
---@param fn fun(...):any generate Function
|
|
---@param rfn fun(...):any reset Function
|
|
---@param name? string for debug purposes
|
|
---@param max? number pool max size
|
|
---@param efn? fun(...):boolean equal Function
|
|
---@return Pool self
|
|
function pool:new(fn, rfn, name, max, efn)
|
|
-- local self = setmetatable({}, pool)
|
|
self.active = {}
|
|
self.hidden = {}
|
|
self.fn = fn
|
|
self.rfn = rfn
|
|
self.efn = efn or defaultEqual
|
|
self.max = max > 0 and max or nil
|
|
self.name = name or "pool"
|
|
return self
|
|
end
|
|
|
|
--- put entity to pool
|
|
---@param self Pool
|
|
---@param entity any
|
|
---@return Pool
|
|
---@return number hidden_idx index from hidden pool
|
|
function pool:put(entity)
|
|
local idx = indexOf(self.active, entity, self.efn)
|
|
if (idx) then
|
|
self:put_to(entity, idx)
|
|
return self, #self.hidden
|
|
else
|
|
print("WARNING : trying to insert entity not from generate function")
|
|
return self, -1
|
|
end
|
|
end
|
|
|
|
--- put entity to pool
|
|
---@param self Pool
|
|
---@param entity any
|
|
---@param idx number
|
|
---@return Pool
|
|
---@return number hidden_idx index from hidden pool
|
|
function pool:put_to(entity, idx)
|
|
if (self.max) then
|
|
if (#self.hidden < self.max) then
|
|
insert(self.hidden, entity)
|
|
else
|
|
self:release(entity)
|
|
end
|
|
else
|
|
insert(self.hidden, entity)
|
|
end
|
|
remove(self.active, idx)
|
|
return self, #self.hidden
|
|
end
|
|
|
|
--- get entity from pool
|
|
---@param self Pool
|
|
---@param ... any
|
|
---@return any entity from pool
|
|
---@return number active_idx
|
|
function pool:get(...)
|
|
local entity = self.hidden[#self.hidden]
|
|
if (entity) then
|
|
insert(self.active, entity)
|
|
remove(self.hidden, #self.hidden)
|
|
self.rfn(entity, ...)
|
|
return entity, #self.active
|
|
else
|
|
entity = self.fn(...)
|
|
insert(self.active, entity)
|
|
return entity, #self.active
|
|
end
|
|
end
|
|
|
|
--- release function
|
|
---@param self Pool
|
|
---@param entity? any
|
|
function pool:release(entity)
|
|
if (entity == nil) then
|
|
for _, v in pairs(self.active) do
|
|
self:release(v)
|
|
end
|
|
for _, v in pairs(self.hidden) do
|
|
self:release(v)
|
|
end
|
|
self.active = nil
|
|
self.hidden = nil
|
|
self.fn = nil
|
|
self.rfn = nil
|
|
self.efn = nil
|
|
self.name = nil
|
|
setmetatable(self, nil)
|
|
self = nil
|
|
else
|
|
local idx = indexOf(self.active, entity, self.efn)
|
|
if (idx) then
|
|
self:release_from("active", idx)
|
|
else
|
|
idx = indexOf(self.hidden, entity, self.efn)
|
|
if (idx) then
|
|
self:release_from("hidden", idx)
|
|
else
|
|
print("WARNING : trying to release object not from generate function")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--- release function
|
|
---@param self Pool
|
|
---@param from_pool "hidden" | "active"
|
|
---@param idx number
|
|
function pool:release_from(from_pool, idx)
|
|
if (from_pool == "hidden") then
|
|
if (self.hidden[idx].release) then
|
|
self.hidden[idx]:release()
|
|
remove(self.hidden, idx)
|
|
else
|
|
print("WARNING : during release hidden, %d don't have release function", idx)
|
|
end
|
|
else
|
|
if (self.active[idx].release) then
|
|
self.active[idx]:release()
|
|
remove(self.active, idx)
|
|
else
|
|
print("WARNING : during release active, %d don't have release function", idx)
|
|
end
|
|
end
|
|
end
|
|
|
|
return pool
|