[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: GC: Island-like with the registry
- From: Julien Danjou <julien@...>
- Date: Fri, 8 May 2009 14:36:03 +0200
Hi,
I've a got a problem right now, and I wonder how I can fix it.
Let me expose you.
I've a type of object that we will call `ninja' (because ninjas
are cool).
Each `ninja' has a weapon: a callback function!
So basically I get a struct defined as:
typedef struct ninja_t {
int weapon;
} ninja_t;
So far so good. Now, when I give a weapon (function) to a ninja, I do:
myninja->weapon = luaL_ref(L, LUA_REGISTRYINDEX);
That set myninja->weapon to a reference number in the registry.
Now, as you know, ninja get killed often, so I store them in a
weak-keyed table:
battles = setmetatable({}, { __mode 'k' })
In the `battles' table, I will store a `mutant' as the key, and a ninja
has the value (we all know that ninja fight mutants).
battles[mymutant] = myninja
So far, so good: as soon as `mymutant' get killed, since it's a
weak-keyed table, myninja will get unref'ed.
BUT.
Now imagine I add a weapon to myninja and then store it:
myninja.weapon = function () kick_ass_of(mymutant) end
battles[mymutant] = myninja
Now, I've something which is like an "island" and will be never garbage
collected. Why? As I understand, that's because myninja.weapon reference
`mymutant'. But, since it's a function stored in the Lua registry, Lua
has no clue that this function is used and store for `myninja'. So it
basically thinks that mymutant has a valid reference.
Schematic:
From my programmer's point of view:
battles[mymutant] --ref--> myninja --ref--> weapon
^----------------ref------------------------'
Cyclic ref, but Lua is smart so can collect.
From real Lua point of view
REGISTRY battles[mymutant]
\ /
\ /
\ ref ref /
\ /
`-> mymutant myninja
Uncollectable: mymutant is refed by the callback function (weapon)
of the ninja in a table (registry), so no reason to kill
battles[mymutant].
I clearly need to tell Lua: "hey buddy, I'm storing things in the
registry for `myninja', so don't think it's totally unrelated".
I am not sure I can do that.
What's the solution guys?
Cheers,
--
Julien Danjou
// ᐰ <julien@danjou.info> http://julien.danjou.info
// 9A0D 5FD9 EB42 22F6 8974 C95C A462 B51E C2FE E5CD
// Don't give up.
Attachment:
signature.asc
Description: Digital signature