lua-users home
lua-l archive

references and userdata...

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


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/>

AltStyle によって変換されたページ (->オリジナル) /