[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: references and userdata...
- From: Michael Cuddy <mcuddy@...>
- Date: Wed, 01 Aug 2001 02:38:17 -0700
Maybe I just don't get it ;-)
I have a couple of CFunctions (actually C++ ;-) which create
userdata objects and return them to LUA. some of these objects
are "containers" and some of these objects are "containees"
con = makeContainer( )
obj = makeObject( )
The 'obj' userdata has a tagmethod (in C++) which overrides "settable" so that
I can do this:
obj["container"] = con
To add the object to the container. (yes, I know, I should make the container
be a table or at least look/act like a table or something, but there are
good API reasons why I'm doing it this way ;-)
The "settable" tag method for the containee-object does this (pseudo code):
obj = lua_touserdata(L,1); // get ptr to object.
index = lua_tostring(L,2);
if (index == "container") { // trying to change container?
int oldCont = obj->container; // get old container, a lua ref
if (oldCont != LUA_NOREF) {
lua_unref(L,oldCont); // release ref to container
}
lua_pushvalue(L,3); // copy of 'container'
obj->container = lua_ref(L,1); // pop locked reference
// now notify containers (old and new)
if (oldCont != LUA_NOREF) {
lua_getref(L,oldCont); // push ref of old container
// and get object.
Container *cont = (Container*)lua_touserdata(L,-1);
lua_pop(L,1); // remove container
cont->remObject(obj); // tell container that 'obj' is gone
}
if (obj->container != LUA_NOREF) {
lua_getref(L,obj->container);// push ref of 'new' container
// and get object.
Container *cont = (Container*)lua_touserdata(L,-1);
lua_pop(L,1); // remove container
cont->addObject(obj); // tell container about 'obj'
}
The code for addObject() looks something like this:
Container::addObject(Object *o)
{
lua_pushusertag(L,o,o->getTag()); // put object on stack
int ref = lua_ref(L,1); // lock reference.
// .. store 'obj' and 'ref' in associative array
// listing contained objects
objects[ref] = obj;
}
Likewise, remObject() looks something like this:
Container::remObject(Object *o)
{
lua_pushusertag(L,o,o->getTag()); // put object on stack
int ref = lua_ref(L,0); // get reference, unlocked
// .. remove 'obj' from associative array
// by removing element 'i'.
objects[ref] = nil;
lua_unref(L,ref);
}
Now, if I execute the following Lua code:
con = makeContainer( ... )
obj = makeObject( ... )
obj["container"] = con
obj = makeObject( ... )
obj["container"] = con
collectgarbage()
What I should end up with is "obj->container" having a locked ref to the
container object and the container knowing that 'obj' is contained within
it and having a lock'ed reference back to the 'obj'.
Howver, in the code listed above, the first object gets garbage collected!
I'm at a loss. I'm using 4.1a ...
Since lua_pushusertag() went away in 4.1a (why?). I have redefined
lua_pushusertag thusly:
#define lua_pushusertag(L,o,tag) \
{ lua_newuserdatabox(L,o); lua_settag(L,tag); }
Any help would be greatly appreciated.
--
Mike Cuddy (mcuddy@FensEnde.com, MC312), Programmer, Daddy, Human.
Fen's Ende Software, Redwood City, CA, USA, Earth, Sol System, Milky Way.
Now I lay me down to sleep / CVS, I pray, my code to keep.
If disks crash before I wake: / format, newfs, cvs up, make.
Join CAUCE: The Coalition Against Unsolicited Commercial E-mail.
<http://www.cauce.org/>