lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


2008/7/29 E. Wing <ewmailing@gmail.com>:
> On 7/28/08, Michael Ferenduros <mike.ferenduros@gmail.com> wrote:
>> You can establish the relationship in two ways:
>> 1) Use luaL_ref() to create a reference to the matrix, and store it in
>> the vector struct. This will pin the Matrix until you release the ref
>> (which you should do when the vector gets gc'd)
>> 2) Stick the matrix in the vector userdata's environment-table. This
>> has the same effect - as long as the vector exists, it'll keep the
>> matrix alive - plus it's a bit more friendly to the garbage-collector.

I'd choose the environment table solution. It costs a little more
memory (a table per vector), but that way you don't pollute the
registry. It's also a bit safer, because any C library could remove
the reference from the registry, or even replace the registry table as
a whole.

> Thanks again for the replies. I haven't done anything with luaL_ref
> and environment tables so I thought I would try both to see how they
> work.
>
> For luaL_ref/unref, I added the __gc metamethod to MyVector so I can
> call luaL_unref. Then for both, I added the following in my __index
> function for MyMatrix where I create the Vector. I think both are
> working and things seem to clean up in the right order at the right
> times, but I would really appreciate it if any body sees any problems
> with the snippet below.
>
>
>                MyVector* return_vector = (MyVector*)lua_newuserdata(lua_state,
> sizeof(MyVector));
>                return_vector->myMatrix2 = the_struct;
>                return_vector->theRow = array_index;
>
> #ifdef USE_LUAREF
>                lua_pushvalue(lua_state, -2-1); // copy the matrix on top of the
> stack: [MyMatrix2 index MyVector MyMatrix2]
>                // Thought: I am creating a unique ID for each vector even though
> the matrix may be shared. I think a better way is to associate an id
> with the matrix and store it there, but I don't want to change my
> MyMatrix2 userdata.
>                int ref_id = luaL_ref(lua_state, LUA_REGISTRYINDEX); // pop the
> matrix off the stack and put it into the registry for referncing
>                return_vector->refID = ref_id;
>
> #elif defined(USE_ENV_TABLE)
>                lua_newtable(lua_state); // stack: [MyMatrix2 index MyVector table]
>
>                lua_pushvalue( lua_state, 1 );  /* Put MyMatrix2 on top of the
> stack. [MyMatrix2 index MyVector table MyMatrix2] */
>                lua_rawseti( lua_state, -2, lua_objlen( lua_state, -2 ) + 1 );    /*
> env[ #env + 1 ] = MyMatrix2, pops MyMatrix2 */

Rather than env[ #env + 1 ] you can simply use env[1], because you
have a 1-1 relationship between the vector and the environments.

>                // stack: [MyMatrix2 index MyVector table]
>                lua_setfenv( lua_state, -2 );    // Makes the table on top of the
> stack the environment table for MyVector (at -2)
>                // stack: [MyMatrix2 index MyVector]
> #endif
>                luaL_getmetatable(lua_state, MYVECTOR_METATABLEID);
>                lua_setmetatable(lua_state, -2);

Another tradeoff you can study, is that with that method you no longer
have to store a pointer to the matrix in the vector structure, since
you can retrieve it from the vector userdata environment. It's a bit
more costly in terms of CPU to retrieve the matrix, but you save a bit
of memory.

>> OTOH, you might want to think hard about whether this is really worth
>> the trouble, and potential for unexpected behaviour. The m[{1,2}]
>> solution looks a lot nicer IMHO.You could also handle m{1,2} if you
>> wanted (but only for getting, not setting).
>
> Yes, I'm not sure if this is worth it, but I wanted to at least know
> how to do it and see if I could do it in this simple test case. I
> still have yet to decide if I want to implement for my real stuff.

Keep in mind that using the m[{x, y}] syntax you are allocating a new
table every time you access your matrix, unless you cache the table.
The environment table above has the same cost (since you allocate a
vector and its env table every time you access the matrix), the
luaL_ref method doesn't have that drawback.