lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


----- Original Message -----
From: Roberto Ierusalimschy
Date: 8/10/2009 10:46 AM
So I guess I'm wondering: is there any reason why Lua doesn't let
userdata have a custom mark function?  It would allow me to implement my
extension much more efficiently.
    
Note that the Lua API does not have anything like a PyObject type. Lua
values have no representation in C at all. So, what would be the use
of a mark function? Where would it get the Lua objects to mark? If the
mark function can access a Lua object, this object is accessible and
therefore will be marked by Lua, without the need of a mark function.
  
I've been meaning to suggest being able to patch into the Lua garbage collector for some time.  LuaPlus can stores its LuaObject C++ objects on the stack or in a C++ object.  When the constructor is called, the LuaObject is added to a linked list of active LuaObjects.  When the destructor is called, the LuaObject is removed from the linked list.

This isn't the same thing as a custom mark function in the style of Python or Ruby, but I think it could be related.

The patch is added to lgc.c (svn://svn.luaplus.org/LuaPlus/work51/Src/LuaPlus/src/lgc.c) in markroot() and atomic():

#if LUAPLUS_EXTENSIONS
  if (G(L)->userGCFunction)
    G(L)->userGCFunction(L);
#endif /* LUAPLUS_EXTENSIONS */

I also provide the ability to set the extra garbage collection function:

    lua_setusergcfunction(L, LuaPlusGCFunction);

Whose implementation is:

#if LUAPLUS_EXTENSIONS
#define markvalue(g,o) { checkconsistency(o); \
  if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }

#define markobject(g,t) { if (iswhite(obj2gco(t))) \
        reallymarkobject(g, obj2gco(t)); }

void LuaPlusGCFunction(void* s)
{
    lua_State* L = (lua_State*)s;
    LuaPlus::LuaState* state = lua_State_To_LuaState(L);
    if (!state)
        return;

    global_State* g = G(L);

    LuaPlus::LuaObject* curObj = (LuaPlus::LuaObject*)G(L)->gchead_next;
    while (curObj != (LuaPlus::LuaObject*)&G(L)->gctail_next)
    {
        markvalue(g, curObj->GetTObject());
        curObj = *(LuaPlus::LuaObject**)curObj;
    }
}
#endif /* LUAPLUS_EXTENSIONS */

Josh