Самостоятельные ссылки на пользовательские данные и сборку мусора - PullRequest
3 голосов
/ 03 мая 2010

Поскольку мои объекты пользовательских данных ссылаются на себя, мне нужно удалить и nil переменную для работы сборщика мусора.

Код Lua:

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

C код:

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 );
}

Есть ли какой-нибудь способ, которым я могу установить объект равным nil в Lua, и чтобы метод delete () вызывался автоматически? Кроме того, может ли метод удаления обнулить все переменные, которые ссылаются на объект? Можно ли сделать ссылку на себя «слабой»?

РЕДАКТИРОВАТЬ 1: я включил код, чтобы показать, почему объект ссылается на себя; см. функцию do_callback. Каждый объект является частью древовидной структуры, большая часть обработки выполняется на C, но пользователь может установить пользовательскую функцию Lua, которая вызывается при определенных условиях.

РЕДАКТИРОВАТЬ 2: Другое возможное решение приходит на ум; Вместо того, чтобы каждый объект сохранял ссылку на себя, могу ли я искать объект в глобальном индексе, когда мне нужно передать его Lua, используя его адрес в качестве ключа?

1 Ответ

1 голос
/ 03 мая 2010

Вы можете попытаться создать слабую таблицу в реестре и сохранить там свои ссылки, таким образом, установив все ссылки на ваш объект на nil, вы должны сделать его доступным для gc.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...