lua-users home
lua-l archive

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


I'm not looking for reference counting or garbage collection behaviour. I am
looking for a way to store a reference to a Lua function so that it can be
called from the C code at a later date, without having to store a string
representing the function name.

I guess what I'm asking is for the original Lua 4.0 behaviour - that lua_ref
would return a unique reference ID for each value passed to it, even if the
lua value is the same.

E.g.
lua_ref(foo) == 3
lua_ref(foo) == 4
lua_ref(foo) == 5
lua_unref(3)
lua_ref(foo) == 3
lua_ref(foo) == 6

>From Roberto's reply to my original post (Lua on the Playstation2), I
inferred that this was the intended behaviour even in Lua 5.0. Hence I
brought it up with the list as a possible issue.

This behaviour occurs immediately after startup, so a lua_open, then a
lua_baselibopen, the lua_register for GetFunctionReference then the call to
this script. The code I posted is exactly the code used to invoke the
problem. Having diffed my source tree and the original lua distribution, I
see the malloc/realloc hooks I wrote, and the search and replace changing
all occurrences of double->float and long->int (required to make Lua 32-bit
under Playstation2).

Tracing through the luaL_ref call, I get the following behaviour - every
single time the function is called

lua_isnil(L, -1) always returns false, because the value being referenced is
not nil
lua_rawgeti(L, t, FREELIST_REF) pushes 0 onto the stack, so the function
goes into the /*no free elements*/ case
luaL_getn(L, t) always returns 0, which is less than RESERVED_REFS, so ref
ends up being 3
The value 3 is used for the rest of the function and eventually returned.

Is this the result that everyone else gets?

-----Original Message-----
From: Vijay Aswadhati [mailto:wyseman@pacbell.net]
Sent: 07 November 2003 07:46
To: 'Lua list'
Subject: RE: lua_ref problem


I am assuming that you are interested in lua_ref for some kind of reference
counting mechanism OR to prevent garbage collection for a class of objects
(including Lua functions) and that you are using Lua 5.0;

I am not sure what specific issues that you are facing, but I can tell you
that luaL_ref and luaL_unref by themselves are too low level and you will
have to build a "tiny" layer on top of these functions.

To cut a long story short, some moons ago I wrote a binding to "Austin" and
I was faced with a class of problems that reference counting seemed to
solve. I wrote a "tiny" layer that you may find useful for learning purpose
or on its own merit.

I am not sure if I can attach to a post, so if you want the code send me an
e-mail and I will send it to you and anyone else who may be interested.
Although I had plans to put it on the wiki it is now deferred indefinitely
since the module is named "ldb" which already taken up by another author for
another module and I am not inclined to spend anymore time on it for the
moment.

Here is a brief descriptions of the functions in the "tiny" layer in "C"
that hides the details of luaL_ref and luaL_unref:

/**
* @brief create a reference pool.
*
* Not required to be called explicitly.
*/
void lni_create_ref_pool(lua_State *L, void *pool);

/**
* @brief destroys a reference pool.
*
* Use with extreme caution since all references after
* this function call MAY be collected by GC.
*/
void lni_destroy_ref_pool(lua_State *L, void *pool);

/**
* @brief Returns the reference to the object on the stack at index
*        <si> in <pool>.
*
* <pool> is really a lightuserdata that is used as an index to a
* global (albeit internal) table.
*
* If the object (at stack index 'si') does not exist in the <pool>
* then it is added to the pool, a luaL_ref value is associated and
* the reference count to this newly added object is set to 1. The
* newly luaL_refd value is returned.
*
* If the object exists in the <pool>, then the reference count is
* bumped up and the luaL_ref value associated with this object is
* returned.
*
* @todo need details on how this impacts the garbage collector,
*       memory consumption and the life cycle of these pinned
*       objects.
*/
int lni_ref(lua_State *L, void *pool, int si);

/**
* @brief Returns a positive integer if the object referenced by
*        <lref> in <pool> is unreferenced succesfully from
*        the <pool>.
*
* <pool> is really a lightuserdata that is used as an index to a
* global (albeit internal) table.
*
* If the object does not exist in the <pool> for whatever reason,
* the return value is LUA_NOREF.
*
* If the object exists in the <pool>, then the reference count is
* reduced by 1.
*
* If the reference count counts down to zero, then then the object
* is luaL_unrefd, the record associated with this object is 'nil'd
* and finally the function returns 0. Otherwise the reference count
* is returned.
*
* @todo need details on how this impacts the garbage collector,
*       memory consumption and the life cycle of these pinned
*       objects.
*/
int lni_unref(lua_State *L, void *pool, int lref);

/**
* Put the value pointed to by lref on the top of the stack
*/
void lni_getref(lua_State *L, void *pool, int lref);


/**
* This function was taken from ltablib.c; it would be
* a useful function for debugging, and testing.
*
* Executes the given func over all elements of table.
* For each element, func is called with the index and
* respective value as arguments. If func returns a
* non-nil value, then the loop is broken, and this
* value is returns as the final value of foreach.
*
* The behaviour of foreach is undefined if you change the
* table t during the traversal.
*/
int lni_foreach (lua_State *L, int ti, int fi);



> -----Original Message-----
> From: lua-bounces@bazar2.conectiva.com.br
> [mailto:lua-bounces@bazar2.conectiva.com.br]On Behalf Of Chris Chapman
> Sent: Thursday, November 06, 2003 7:57 AM
> To: lua@bazar2.conectiva.com.br
> Subject: lua_ref problem
>
>
> Okay, I'm having to revisit this problem, because my original
> workaround is
> insufficient for the other issues that have arisen because of
> it. I hope
> someone here can see what I'm doing wrong.
>
> Given the script:
>
> do
> 	function foo()
> 		print("foo\n");
> 	end
>
> 	function bar()
> 		print("bar\n");
> 	end
>
> 	print (GetFunctionReference(foo) .. "\n");
> 	print (GetFunctionReference(foo) .. "\n");
> 	print (GetFunctionReference(bar) .. "\n");
> 	print (GetFunctionReference(foo) .. "\n");
> end
>
> and "GetFunctionReference" being a C function registered with
> lua which
> looks like:
>
> int		GetFunctionReference(lua_State*	L)
> {
> 	//get a reference to the first argument on the stack
>
> 	//check the argument is a lua function
> 	if (lua_type(L, -1) == LUA_TFUNCTION)
> 	{
> 		int		iReference	=	lua_ref(L, 1);
> //1 indicates a locked reference
>
> 		//return the reference index as a number
> 		lua_pushnumber(L, iReference);
> 		return 1;
> 	}
> 	else
> 	{
> 		return 0;
> 	}
> }
>
> Running this script produces the output:
>
> 3
> 3
> 3
> 3
>
> I.e. no matter what I try to pass to lua_ref, I always get 3 back as a
> reference. Breakpointing the C code indicates that it is
> indeed 3 being
> returned from lua_ref each time. Tracing the lua code follows
> the same path
> each call.
>
> Again, this is a difference between 4.0.1 and 5.0.
>
> Thanks
> ChrisC
>