[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: GC: Island-like with the registry
- From: Duncan Cross <duncan.cross@...>
- Date: Fri, 8 May 2009 13:48:36 +0100
On Fri, May 8, 2009 at 1:36 PM, Julien Danjou <julien@danjou.info> wrote:
> 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.
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iEYEARECAAYFAkoEJzAACgkQpGK1HsL+5c1srwCfSp1R2dd49565Vxk5AXBLqc/K
> NbAAn0qwAlrYa5q2l9vTIIJfe6ISnptm
> =ArOx
> -----END PGP SIGNATURE-----
>
>
There is probably a better way than using luaL_ref and luaL_unref to
associate a callback with your myninja object. I assume myninja is a
full userdata in the Lua universe - if so, I would give myninja a
unique "environment" table (lua_setfenv and lua_getfenv work on full
userdata, and are only available from the API), and have the weapon
callback be a normal key-value entry in that. If not, what is it, a
light userdata?
-Duncan