/* * void= mt.__gc( proxy_ud ) * * End of life for a proxy object; reduce the deep reference count and clean * it up if reaches 0. */ static int deep_userdata_gc( lua_State *L ) { DEEP_PRELUDE **proxy= (DEEP_PRELUDE**)lua_touserdata( L, 1 ); DEEP_PRELUDE *p= *proxy; int v; *proxy= 0; // make sure we don't use it any more MUTEX_LOCK( &deep_lock ); v= --(p->refcount); MUTEX_UNLOCK( &deep_lock ); if (v==0) { int pushed; // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup // lua_CFunction idfunc= get_idfunc(L,1); ASSERT_L(idfunc); lua_settop(L,0); // clean stack so we can call 'idfunc' directly // void= idfunc( "delete", lightuserdata ) // lua_pushliteral( L, "delete" ); lua_pushlightuserdata( L, p->deep ); pushed= idfunc(L); if (pushed) luaL_error( L, "Bad idfunc on \"delete\": returned something" ); DEEP_FREE( (void*)p ); } return 0; }
/* * Access deep userdata through a proxy. * * Reference count is not changed, and access to the deep userdata is not * serialized. It is the module's responsibility to prevent conflicting usage. */ void *luaG_todeep( lua_State *L, lua_CFunction idfunc, int index ) { DEEP_PRELUDE **proxy; STACK_CHECK(L) if (get_idfunc(L,index) != idfunc) return NULL; // no metatable, or wrong kind proxy= (DEEP_PRELUDE**)lua_touserdata( L, index ); STACK_END(L,0) return (*proxy)->deep; }
/* * Access deep userdata through a proxy. * * Reference count is not changed, and access to the deep userdata is not * serialized. It is the module's responsibility to prevent conflicting usage. */ void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) { DEEP_PRELUDE** proxy; STACK_CHECK( L); // ensure it is actually a deep userdata if( get_idfunc( L, index, eLM_LaneBody) != idfunc) { return NULL; // no metatable, or wrong kind } proxy = (DEEP_PRELUDE**) lua_touserdata( L, index); STACK_END( L, 0); return (*proxy)->deep; }
/* * Copy deep userdata between two separate Lua states (from L to L2) * * Returns: * the id function of the copied value, or NULL for non-deep userdata * (not copied) */ luaG_IdFunction copydeep( struct s_Universe* U, lua_State* L, lua_State* L2, int index, enum eLookupMode mode_) { char const* errmsg; luaG_IdFunction idfunc = get_idfunc( L, index, mode_); if( idfunc == NULL) { return NULL; // not a deep userdata } errmsg = push_deep_proxy( U, L2, *(DEEP_PRELUDE**) lua_touserdata( L, index), mode_); if( errmsg != NULL) { // raise the error in the proper state (not the keeper) lua_State* errL = (mode_ == eLM_FromKeeper) ? L2 : L; luaL_error( errL, errmsg); } return idfunc; }
/* * Copy deep userdata between two separate Lua states. * * Returns: * the id function of the copied value, or NULL for non-deep userdata * (not copied) */ static lua_CFunction luaG_copydeep( lua_State *L, lua_State *L2, int index ) { DEEP_PRELUDE **proxy; DEEP_PRELUDE *p; lua_CFunction idfunc; idfunc= get_idfunc( L, index ); if (!idfunc) return NULL; // not a deep userdata // Increment reference count // proxy= (DEEP_PRELUDE**)lua_touserdata( L, index ); p= *proxy; luaG_push_proxy( L2, idfunc, p ); // // L2 [-1]: proxy userdata return idfunc; }