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.
172 lines
6.6 KiB
172 lines
6.6 KiB
|
5 years ago
|
--===========================================================================--
|
||
|
|
-- --
|
||
|
|
-- 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)
|