ObjectsByName.lua - Garbage-collection friendly name-object & object-name mapping facility.

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]

Please discard the previous posting… working on something “better”…

-FS.
[import]uid: 8093 topic_id: 7113 reply_id: 25062[/import]

I’m excited to see what you come up with next! :slight_smile: [import]uid: 5833 topic_id: 7113 reply_id: 25215[/import]

Beware what you wish for… :wink: [import]uid: 8093 topic_id: 7113 reply_id: 25234[/import]

:slight_smile: [import]uid: 5833 topic_id: 7113 reply_id: 25434[/import]