2010-05-02 34 views
2

因爲我的用戶數據對象引用自己,我需要刪除零垃圾收集工作的一個變量。自參照用戶數據和垃圾收集

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

有一些方法我可以設置對象在Lua爲零,並有自動調用了delete()方法?或者,刪除方法是否可以刪除引用該對象的所有變量?自我參照能力是否「虛弱」?

編輯1:我已經包含代碼,說明爲什麼對象引用本身;請參閱do_callback函數。每個對象都是樹狀結構的一部分,其中大部分處理是用C完成的,但用戶可以設置在某些條件下調用的自定義Lua函數。

編輯2:想到另一種可能的解決方案;而不是每個obj保持對自身的引用,當我需要將它的地址作爲關鍵字傳遞給Lua時,我可以在全局索引中查找對象嗎?

+0

我不會給這個作爲一個正常的答案,因爲我不知道如何解決你的整個問題,但你看着Lua的__gc - 元方法? – ponzao 2010-05-03 05:21:33

+0

userdata具有__gc回調;但直到在delete()中刪除自引用後纔會調用它,並且指向userdata的所有變量均爲零。 – 2010-05-03 05:56:38

+0

爲什麼你需要一個自我參考?在C端可以存儲(Object *)obj,並依靠__gc清理;在Lua方面你有obj。 – 2010-05-03 15:44:47

回答

1

您可以嘗試在註冊表中創建一個弱表並將您的引用存儲在那裏,這樣將您的對象的所有引用設置爲零應該使其可用於gc。

+0

這取決於自我引用的用途,所以我問drtwox這個問題。如果正在使用自引用來防止收集用戶數據,則弱引用將不起作用。對於其他用途,您的解決方案很好,但我更喜歡圖書館環境中的弱桌。 – 2010-05-03 15:47:56