Self-referenced user data and garbage collection

As my userdata objects refer to them, I need to delete and nil variable, so the garbage collector work.

Lua code:

obj = object:new()
-- 
-- Some time later
obj:delete()  -- Removes the self reference
obj = nil     -- Ready for collection

      

C Code:

typedef struct {
    int self; // Reference to the object
    int callback; // Reference to a Lua function
    // Other members and function references removed
} Object;

// Called from Lua to create a new object
static int object_new( lua_State *L ) {
    Object *obj = lua_newuserdata( L, sizeof( Object ) );

    // Create the 'self' reference, userdata is on the stack top
    obj->self = luaL_ref( L, LUA_REGISTRYINDEX );

    // Put the userdata back on the stack before returning
    lua_rawgeti( L, LUA_REGISTRYINDEX, obj->self );

    // The object pointer is also stored outside of Lua for processing in C

    return 1;
}

// Called by Lua to delete an object
static int object_delete( lua_State *L ) {
    Object *obj = lua_touserdata( L, 1 );

    // Remove the objects self reference
    luaL_unref( L, LUA_REGISTRYINDEX, obj->self );

    return 0;
}

// Called from Lua to set a callback function
static int object_set_callback( lua_State *L ) {
    Object *obj = lua_touserdata( L, 1 );

    // Unref an existing callbacks
    if ( obj->callback != 0 ) {
        luaL_unref( L, LUA_REGISTRYINDEX, obj->callback );
        obj->callback = 0;
    }

    // Set the new callback - function is on top of the stack
    obj->callback = luaL_ref( L, LUA_REGISTRYINDEX );
}

// Called from C to call a Lua function for the obj
static void do_callback( Object *obj ) {
    // Push the Lua function onto the stack
    lua_rawgeti( L, LUA_REGISTRYINDEX, obj->callback );

    // Push the userdata onto the stack
    lua_rawgeti( L, LUA_REGISTRYINDEX, obj->self );

    // Call the function
    lua_call( L, 1, 0 );
}

      

Is there some way to set an object to nil in Lua and call the delete () method automatically? Alternatively, can the delete method use all the variables that reference the object? Can self-awareness be "weak"?

EDIT 1: I have included code to show why the object is being referenced by itself; see the do_callback function. Each object is part of a tree structure, with most of the processing done in C, but the user can set up a custom Lua function that gets called under certain conditions.

EDIT 2: Another possible solution comes to mind; Instead of having each obj store a reference to itself, can I find the object in the global index when I need to pass it to Lua using its address as a key?

+2


a source to share


1 answer


You can try to create a weak table in the registry and store your references there. Thus, setting all references of your object to nil should make it available to gc.



+1


a source







All Articles