[SOLVED] texture manager. Garbage collection issue

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
mode7
Prole
Posts: 35
Joined: Tue Aug 21, 2012 5:45 pm
Contact:

[SOLVED] texture manager. Garbage collection issue

Post by mode7 » Fri May 17, 2013 4:26 pm

Hello everyone.

I'm working on a game engine, that loads assets from a map format (Gleed2d). Let's say there are 5 identical trees, then the engine will load 'res/tree.png' as an image for each game object.

Doing this using love.graphics.newImage('res/tree.png') will take up 5x the memory, as love loads each asset as a new texture.
...
Obviously not the smart way to go. To make the engine share already loaded assets, I created a texture manager:
Pretty straightforward.

Code: Select all

local textureMngr = sclass()
function textureMngr:init()
	self.textures = {}
end

function textureMngr:load(filename)
	if not self.textures[filename] then self.textures[filename] = love.graphics.newImage(filename) end
	return self.textures[filename]
end
	
function textureMngr:getFilename(texture)
	for i,v in pairs(self.textures) do
		if texture == v then return i end
	end
end

function textureMngr:delete(id)
	if type(id) == "string" then
		self.texture[id] = nil
	else
		self.texture[self:getFilename(id)] = nil
	end
end

texture = textureMngr()
So instead of love.graphics.newImage, I just call texture:add(filename) and either get a new image object or a previously loaded one. Works flawless so far.

But there's one downside of this. Since all the image object are stored in the texture managers table, they don't get collected by luas garbage collection when no other game instance is pointing to it, since it's still accessible through the texture manager.

So if I want to load another map, I'm either stuck with all the old images still in memory or manually have to delete them.
Is there some way to determine if no other table except the index in the image manager is pointing to the image userdata object.
Last edited by mode7 on Fri May 17, 2013 6:52 pm, edited 1 time in total.

User avatar
markgo
Party member
Posts: 189
Joined: Sat Jan 05, 2013 12:21 am
Location: USA

Re: Creating an image/texture manager. Garbage collection is

Post by markgo » Fri May 17, 2013 5:37 pm


mode7
Prole
Posts: 35
Joined: Tue Aug 21, 2012 5:45 pm
Contact:

Re: Creating an image/texture manager. Garbage collection is

Post by mode7 » Fri May 17, 2013 5:48 pm

Seems to be exactly what I was looking for.
I'll have a look into weak tables and post the solution here.

Thanks a lot!

EDIT: Adding one line of code does the trick. Thank you very much markgo. I'll mark this as solved.

Code: Select all

local textureMngr = sclass()
function textureMngr:init()
	self.textures = {}
    setmetatable(self.textures, {__mode="v"})
end

function textureMngr:load(filename)
	if not self.textures[filename] then self.textures[filename] = love.graphics.newImage(filename) end
	return self.textures[filename]
end
	
function textureMngr:getFilename(texture)
	for i,v in pairs(self.textures) do
		if texture == v then return i end
	end
end

function textureMngr:delete(id)
	if type(id) == "string" then
		self.texture[id] = nil
	else
		self.texture[self:getFilename(id)] = nil
	end
end

texture = textureMngr()

Post Reply

Who is online

Users browsing this forum: Google [Bot] and 64 guests