lua-users home
lua-l archive

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


On Mar 16, 2010, at 3:54 PM, Luiz Henrique de Figueiredo wrote:

>> I know that deep copy function. I need a function in C. I'm going to be
>> passing lua tables between pthreads, these are separate lua states.
>> So i have to take a table of one stack copy and push it onto another stack.
> 
> Here's is totally untested code, just to give you an idea.
> 
> static int xcopy1(lua_State *L, lua_State *T, int n)
> {
> switch (lua_type(L,n))
> {
>  case LUA_TNIL:
>    lua_pushnil(T);
>    break;
>  case LUA_TBOOLEAN:
>    lua_pushboolean(T,lua_toboolean(L,n));
>    break;
>  case LUA_TNUMBER:
>    lua_pushnumber(T,lua_tonumber(L,n));
>    break;
>  case LUA_TSTRING:
>    lua_pushlstring(T,lua_tostring(L,n),lua_strlen(L,n));
>    break;
>  case LUA_TLIGHTUSERDATA:
>    lua_pushlightuserdata(T,(void*)lua_touserdata(L,n));
>    break;
>  default:
>    assert(0);
>    break;
> }
> }
> 
> /* table is in the stack at index 't' */
> static int xcopy(lua_State *L, lua_State *T, int t)
> {
> int w;
> lua_newtable(T);
> w=lua_gettop(T);
> lua_pushnil(L);  /* first key */
> while (lua_next(L, t) != 0) {
> 	xcopy1(L,T,-2);
> 	if (lua_type(L,-1)==LUA_TTABLE)
> 		xcopy(L,T,lua_gettop(L));
> 	else
> 		xcopy1(L,T,-1);
> 	lua_settable(T,w);
> 	lua_pop(L,1);
> }
> }

Having written similar code in the past, here are some notes on Luiz's generally nice and certainly concise code:

1. It doesn't handle tables as keys. But it does assert so you at least won't continue blindly on (though you may still not be happy when assert terminates the program). This probably doesn't matter for your intended use case.
2. It doesn't recognize shared tables. This probably isn't an issue for your use case.
3. It doesn't depth check. This is only a problem if you have cyclic data structures.
4. It has trickier error behavior than one would like because you can get errors on either Lua state and probably at least one of these isn't running protected at this point.

Of these, only the fourth really matters in most cases, but it's a pain to fix. If you depth limit, you can grow the source stack and then do everything within a cpcall for the destination state though you then have to worry about how to get a value out of the cpcall. Lua 5.2, I believe, addresses that. Otherwise, you stick it in the registry or you do the work in a temporary Lua thread and then transfer it to the stack for the main thread (though of course that requires allocating the temporary thread safely...) Lua 5.2 may make some of the other logic simpler as well through its improved cpcall interface.

Serialization in one state and deserialization in another becomes very tempting because it also allows one to reduce synchronization.

Mark