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

171 lines
6.6 KiB

--===========================================================================--
-- --
-- System.Recycle --
-- --
--===========================================================================--
--===========================================================================--
-- Author : kurapica125@outlook.com --
-- URL : http://github.com/kurapica/PLoop --
-- Create Date : 2015/07/22 --
-- Update Date : 2018/03/15 --
-- Version : 1.0.0 --
--===========================================================================--
PLoop(function(_ENV)
namespace "System"
--- Recycle is used as an object factory and recycle manager.
--
-- Recycle's constructor receive a class or struct as it's first argument,
-- the class|struct would be used to generate a new object for recycling.
-- The other arugments for the constructor is passed to the class|struct's
-- constructor as init arugments, if one argument is string and containts
-- '%d', the '%d' will be converted to the factory index.The factory index
-- in alwasy increased by 1 when a new object is created.
--
-- After the recycle object is created as 'recycleObject', you can use
-- 'recycleObject()' to get an object, and use 'recycleObject(object)'
-- to put the object back for another query.
--
-- ry = Recycle( class { print }, "Name%d" )
-- -- table: 00FA96B0 Name1
-- o = ry()
-- -- table: 00F4B730 Name2
-- o = ry()
--
-- Also you can give the recycle object a "New" method used to generate the
-- new object if the creation of the recycled object is too complex like :
--
-- -- The class would print all arguments when its object created
-- ry = Recycle( class { print } )
--
-- function ry:New()
-- -- Add a count for it
-- self.Cnt = (self.Cnt or 0) + 1
-- return self.Type(self.Cnt)
-- end
--
__Sealed__() __NoRawSet__(false) __NoNilValue__(false)
class "Recycle" (function(_ENV)
export {
type = type,
ipairs = ipairs,
unpack = table.unpack or unpack,
tinsert = table.insert,
tremove = table.remove,
strfind = string.find,
strformat = string.format,
}
-----------------------------------------------------------
-- event --
-----------------------------------------------------------
--- Fired when an no-used object is put in
-- @param object
event "OnPush"
--- Fired when an un-used object is send out
-- @param object
event "OnPop"
--- Fired when a new object is created
-- @param object
event "OnInit"
local function parseArgs(self, ...)
local index = (self.__index or 0) + 1
self.__index = index
local cache = self.__args or {}
for i, arg in ipairs(self.__arguments) do
if type(arg) == "string" and strfind(arg, "%%d") then
arg = strformat(arg, index)
end
cache[i] = arg
end
self.__args = cache
return unpack(cache)
end
-----------------------------------------------------------
-- method --
-----------------------------------------------------------
--- Create a new recycled object, should be overwrited
function New(self)
if not self.Type then
return {}
elseif self.__arguments then
if self.__needparse then
return self.Type(parseArgs(self))
else
return self.Type(unpack(self.__arguments))
end
else
return self.Type()
end
end
--- Push object into the recycle bin
-- @param object the object that put in
function Push(self, obj)
if obj then
for i, v in ipairs(self) do if v == obj then return end end
-- Won't check obj because using cache means want quick-using.
tinsert(self, obj)
return OnPush(self, obj)
end
end
--- Pop object from recycle bin
-- @return object the object that pop out
function Pop(self)
local ret = tremove(self)
if not ret then
ret = self:New()
OnInit(self, ret)
end
OnPop(self, ret)
return ret
end
-----------------------------------------------------------
-- property --
-----------------------------------------------------------
--- The recycled object's type
property "Type" { Type = StructType + ClassType }
-----------------------------------------------------------
-- constructor --
-----------------------------------------------------------
__Arguments__{ Variable("type", StructType + ClassType, true), Any * 0 }
function Recycle(self, cls, ...)
if cls then
self.Type = cls
self.__arguments = select('#', ...) > 0 and {...} or false
if self.__arguments then
self.__needparse = false
for _, arg in ipairs(self.__arguments) do
if type(arg) == "string" and arg:find("%%d") then
self.__needparse = true
break
end
end
end
end
end
-----------------------------------------------------------
-- meta-method --
-----------------------------------------------------------
function __call(self, obj) if obj then return self:Push(obj) else return self:Pop() end end
end)
end)