From 4ead29262bdfab25d6253f70c2fb884112afacb0 Mon Sep 17 00:00:00 2001 From: "Johnny C. Lam" Date: Sun, 10 Nov 2013 00:31:19 +0000 Subject: [PATCH] Add new module that manages pools of reference-counted tables. This implementation is intrusive -- it adds additional properties to the tables that it returns from the pools. git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@1148 d5049fe3-3747-40f7-a4b5-f36d6801af5f --- Ovale.toc | 1 + OvalePoolRefCount.lua | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 OvalePoolRefCount.lua diff --git a/Ovale.toc b/Ovale.toc index 3759be6..1d5196d 100644 --- a/Ovale.toc +++ b/Ovale.toc @@ -28,6 +28,7 @@ OvaleGUID.lua OvaleLatency.lua OvalePool.lua OvalePoolGC.lua +OvalePoolRefCount.lua OvalePower.lua OvaleQueue.lua OvaleSpellBook.lua diff --git a/OvalePoolRefCount.lua b/OvalePoolRefCount.lua new file mode 100644 index 0000000..7a1f9e2 --- /dev/null +++ b/OvalePoolRefCount.lua @@ -0,0 +1,122 @@ +--[[-------------------------------------------------------------------- + Ovale Spell Priority + Copyright (C) 2013 Johnny C. Lam + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License in the LICENSE + file accompanying this program. +--]]-------------------------------------------------------------------- + +--[[ + Reference-counting table pool. + + Tables from the pool have four properties added automatically: + + _refcount_pool_object reference to pool from which the table came. + GetReference() increments the count of references to this table. + ReleaseReference() decrements the count of references to this table and + releases the table back to the pool if then count is zero. + ReferenceCount() the count of references to this table. +--]] + +local _, Ovale = ... +local OvalePoolRefCount = Ovale:NewModule("OvalePoolRefCount") +Ovale.OvalePoolRefCount = OvalePoolRefCount + +-- +local assert = assert +local setmetatable = setmetatable +local tinsert = table.insert +local tostring = tostring +local tremove = table.remove +local wipe = table.wipe +-- + +-- +OvalePoolRefCount.name = "OvalePoolRefCount" +OvalePoolRefCount.pool = nil +OvalePoolRefCount.refcount = nil +OvalePoolRefCount.size = 0 +OvalePoolRefCount.unused = 0 +OvalePoolRefCount.__index = OvalePoolRefCount +-- + +-- +local function ReferenceCount(item) + return item._refcount_pool_object.refcount[item] or 0 +end + +local function GetReference(item) + local refcount = item:ReferenceCount() + item._refcount_pool_object.refcount[item] = refcount + 1 + return item +end + +local function ReleaseReference(item) + local refcount = item:ReferenceCount() + local poolObject = item._refcount_pool_object + if refcount > 1 then + poolObject.refcount[item] = refcount - 1 + else + poolObject.refcount[item] = nil + wipe(item) + tinsert(poolObject.pool, item) + poolObject.unused = poolObject.unused + 1 + end + return item +end +-- + +-- +local itemPrototype = { + _refcount_pool_object = nil, + AddReference = AddReference, + ReferenceCount = ReferenceCount, + ReleaseReference = ReleaseReference, +} +-- + +-- +do + -- Class constructor + setmetatable(OvalePoolRefCount, { __call = function(self, ...) return self:NewPool(...) end }) +end + +function OvalePoolRefCount:NewPool(name) + name = name or self.name + local obj = setmetatable({ name = name }, self) + obj.refcount = {} + obj:Drain() + return obj +end + +function OvalePoolRefCount:Get() + assert(self.pool and self.refcount) + local item = tremove(self.pool) + if item then + self.unused = self.unused - 1 + else + self.size = self.size + 1 + item = {} + end + for name, method in pairs(itemPrototype) do + item[name] = method + end + item._refcount_pool_object = self + return item:GetReference() +end + +function OvalePoolRefCount:Release(item) + item:ReleaseReference() +end + +function OvalePoolRefCount:Drain() + self.pool = {} + self.size = self.size - self.unused + self.unused = 0 +end + +function OvalePoolRefCount:Debug() + Ovale:FormatPrint("Pool %s has size %d with %d item(s).", tostring(self.name), self.size, self.unused) +end +-- -- 1.7.9.5