Jump to content
  • Advertisement
Sign in to follow this  
DrTwox

Circular references and garbage collection in LUA

This topic is 3115 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, I'll start by saying this is probably a trivial concern, but it's been bothering me all afternoon. The collective wisdom here has never failed me before! My Lua userdata objects contain a reference to themselves so C functions can pass the objects to Lua callback functions:
// Code stripped down to the bare essentials!

typedef struct {
    int self; // Reference to the object
    int callback; // Reference to a function 
} Object;


// Called from Lua to create a new object
static int new_object( 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 from Lua to set a callback function for an object
static int set_callback( lua_State *L ) {
    Object *obj = lua_touserdata( L, 1 );

    // Unref any previous callback functions
    if ( obj->callback != 0 ) luaL_unref( L, LUA_REGISTRYINDEX, obj->callback );

    // Reference the new callback
    obj->callback = luaL_ref( L, LUA_REGISTRYINDEX );

    return 0;
}


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

    if ( obj->callback != 0 ) luaL_unref( L, LUA_REGISTRYINDEX, obj->callback );

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

    return 0;
}


// Called by the Lua garbage collector
static int gc_collect( lua_State *L ) {
    // Do cleanup stuff
    return 0;
}

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

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

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

Each object shares a metatable for various methods, and a __gc callback for the garbage collector; nothing unusual there. The main loop in C runs, calls any Lua callbacks required by the objects and all works well. My grief is the deletion of the object when it is no longer required: In Lua:
-- Setup
obj = Object:new()
obj:set_callback( some_lua_function )

-- Elsewhere, some time later
obj:delete() -- required to remove the self reference
obj = nil

I have to call both 'obj:delete()' and 'obj = nil' for the GC to release the resources. Is there a way for the delete() function to nil any Lua variables that reference the userdata object? Some other solution would be most welcome!

Share this post


Link to post
Share on other sites
Advertisement
A solution was suggested elsewhere: Store the 'self' reference in a weak table and the delete() method is no long required!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!