lua-users home
lua-l archive

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


On Jan 10, 2011, at 4:14 AM, Daniel Silverstone wrote:

> On Mon, Jan 10, 2011 at 10:07:51AM -0200, Roberto Ierusalimschy wrote:
>> Instead of a reference, can't you use the address of this small
>> structure as the key to the callback (as a light userdata)? Or the
>> address of a dummy 'ref' field, if you must keep more than one
>> reference?
> 
> I suggested that in a conversation a few of us were having recently (not on
> list or IRC) and it was pointed out to me that pushing and then looking up a
> light userdata in a table, may be more expensive than a rawgeti invocation.
> 
> Dunno if that becomes part of the argument one way or the other.

I've thought about breaking the C API encapsulation and writing:

	lua_gettable_ud( L, t_index, ud )
	lua_settable_ud( L, t_index, ud )

Or raw versions of the same since in the cases where I use them I rarely want the metamethod logic kicking in.

These can almost be written quite easily with the C API, e.g.:

	void lua_gettable_ud( lua_State* L, int t_index, void* ud ) {
		lua_pushlightuserdata( L, ud );
		lua_gettable( L, t_index ); /* BUGGY: See below */
	}

The above code, however, really needs to normalize t_index so that it isn't fouled by the push. It also does extra stack manipulation. Both issues are fine from the standpoint of keeping the C API small, but if light userdata keys are to be the standard idiom for storing references from native code, then it might be good to optimize that path.

Mark

P.S. Here's a version (not copied from actual code) of my push a proxy to a native object logic. It returns 1 leaving the proxy on the top of the stack unless createProxy is 0 and there was no pre-existing proxy in which case it returns 0 and leaves the stack unchanged. If you need to kill proxies early, then you may want to move the static variable being used to define proxyTable outside of the function.

	int pushNativeObjectProxy( lua_State* L, object* obj, int createProxy ) {

		static char proxyTable;

		int proxyTableIndex;
		int success = 0;

		lua_gettable_ud( L, LUA_REGISTRYINDEX, &proxyTable );

		if( lua_isnil( L, -1 ) ) {
			lua_pop( L, 1 );
			lua_newtable( L );
			lua_createtable( L, 0, 1 );
			lua_pushliteral( L, "kv" );
			lua_setfield( L, -2, "__mode" );
			lua_setmetatable( L, -2 );
		}

		proxyTableIndex = lua_gettop( L );

		lua_gettable_ud( L, proxyTableIndex, obj );

		if( !lua_isnil( L, -1 ) ) {
			success = 1;
		} else {
			lua_pop( L, 1 );
			if( createProxy ) {
				buildObjectProxy( L, obj );
				lua_pushvalue( L, -1 ); /* duplicate */
				lua_setttable_ud( L, proxyTableIndex, obj );
				success = 1;
			}
		}

		lua_remove( L, proxyTableIndex );

		return success;

	}