Please take a look at the following - my suggestion is to use a facility like this with Lime to maintain those “by name” mappings of objects and functions. The main reason for writing this is my concern of indadvertedly holding on to deleted object references which will impede their collection.
Comments?
-FrankS.
[lua]–[[
– ObjectsByName.lua - Garbage-collection friendly name-object & object-name mapping facility.
– Copyright © Frank Siebenlist. All rights reserved.
– The use and distribution terms for this software are covered by the
– Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php).
– By using this software in any fashion, you are agreeing to be bound by
– the terms of this license.
– You must not remove this notice, or any other, from this software.
–
– When you try to link sprites to event-handlers, and state-changes to changeState-handlers,
– and buttons to button-handlers, etc., and you want to keep as much of your code outside of the
– hard-coded imperitive Lua, and in declaritive config files and GUI-properies, then you soon
– will try to work with string-name abstractions that have to map to your objects and handlers
– during runtime. The danger with those mappings is that they will normally hold-on to object
– references and therefor make the garbagecollection less effective (…understatement…).
– This ObjectsByName facility manages the name-object and object-name mapping in weak-tables,
– and should therefor be “garbage-collection friendly”.
– The only issue is that the mapping entries of deleted objects will remain in the tables
– until the garbage collector kicks in - when the latter happens is unpredictable.
– Therefor, when the program logic relies on it, one has to explicitly remove mapping entries,
– even though those entries would be removed automagically by the garbage collector at some
– unknown time in the future. In other words, this facility only solves the issue of preventing
– the garbage collector to do its work, but coders still have to worry about deleted references
– for application logic - call removeObjectByName() explicitly if you know an object is removed!.
–
– Enjoy, Frank.
–]]
module(…, package.seeall)
local NameForObjectT = setmetatable({}, {__mode = ‘k’})
local ObjectForNameT = setmetatable({}, {__mode = ‘v’})
— Register anObject and an associated aName in a weak-tables registration system.
– Any previous registration for that anObject or that aName will be overwritten.
function registerObjectByName(anObject,aName)
assert( type(aName) == “string”, “ObjectByName.register: aName has to be a string” )
assert(type(anObject) == “table” or type(anObject) == “function” or type(anObject) == “userdata”, “ObjectByName.register: anObject has to be a reference to a table-like”)
NameForObjectT[anObject] = aName
ObjectForNameT[aName] = anObject
end
— Returns the registered object for aName.
function objectForName(aName)
return ObjectForNameT[aName]
end
— Returns the registered name for anObject.
function nameForObject(anObject)
return NameForObjectT[anObject]
end
— Removes entry for given object or name from registration system.
– Note that this removal is not required for garbage collection,
– but is purely a facility for application level mapping management.
–@param aNameOrObject - if string removes entry associated with that name - if object removes entry associated with that object.
function removeObjectByName(aNameOrObject)
if(aNameOrObject == nil)then return end – bad corner case
if(type(aNameOrObject) == “string”)then
local aName = aNameOrObject
local anObject = ObjectForNameT[aName]
if anObject then
ObjectForNameT[aName] = nil
NameForObjectT[anObject] = nil
end
else
local anObject = aNameOrObject
local aName = NameForObjectT[anObject]
if aName then
ObjectForNameT[aName] = nil
NameForObjectT[anObject] = nil
end
end
end
function dump()
print(“start ObjectsByName.dump”)
for k,v in pairs(NameForObjectT)do
print(“NameForObjectT:”,k,v)
end
for k,v in pairs(ObjectForNameT)do
print(“ObjectForNameT:”,k,v)
end
print(“end ObjectsByName.dump”)
end[/lua]
[lua]-- main.lua
– Some use cases to test ObjectsByName.lua
require(“ObjectsByName”)
print(“start main”)
function try()
local a = {}
ObjectsByName.registerObjectByName(a, “name-”…“try”)
– ObjectsByName.dump()
end
try()
local b = {}
ObjectsByName.registerObjectByName(b, “name-”…“b”)
local c = {}
ObjectsByName.registerObjectByName(c, “name-”…“c”)
local d = {}
ObjectsByName.registerObjectByName(d, “name-”…“d”)
local e = {}
ObjectsByName.registerObjectByName(e, “name-”…“e”)
ObjectsByName.dump()
b = nil
print(“b = nil - collectgarbage”)
collectgarbage()
ObjectsByName.dump()
c = nil
print(“c = nil - collectgarbage”)
collectgarbage()
ObjectsByName.dump()
print(“remove d by name”)
ObjectsByName.removeObjectByName(“name-d”)
ObjectsByName.dump()
print(“remove e by object”)
ObjectsByName.removeObjectByName(e)
ObjectsByName.dump()
print(“end main”)[/lua]
[import]uid: 8093 topic_id: 7113 reply_id: 307113[/import]