lua-users home
lua-l archive

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


On Mon, Nov 30, 2009 at 03:52:37PM -0800, Chris Gagnon wrote:
>    Since ref and the corresponding rawgeti are the fast methods for table
>    access i use the following code to create myself a new co routine.�
> 
>      lua_getfield(MainState, LUA_GLOBALSINDEX, "ThreadTable");
>      lua_State *thread = lua_newthread(MainState);
>      int refID = luaL_ref(MainState, -2);
>      lua_pop(MainState,1);
> 
>    So now the when i want to let GC clean up the coroutine i need to :
> 
>      lua_getfield(MainState, LUA_GLOBALSINDEX, "ThreadTable");
>      luaL_unref(MainState, -1, refID );
> 
>    The remaining piece is where do i get refID when i want to unref? or how
>    do I store that refID with the co routine?
>    Here are some of the possibilities/issues i have run into.
> 
>      * Environment table
>        I have multiple co routines sharing an environment which dosn't allow
>        me to uniquely store this value,
>        without another table which is undesirable from a
>        complexity/performance standpoint
>      * Stack
>        Since the new stack is the only thing completely unshared when
>        creating a co routine, I simply push the value onto the stack.
>        This works like a charm until an error case, errors leave the stack in
>        the layout of the function that ran into the problem.
>        In this case i do not know how to recover the refID to properly clean
>        up.
> 
>    Thoughts about my specific issues?
>    Other suggestions/approaches that i haven't mentioned?

Can you control the body of the coroutines? If so, pass the refID to
them in their opening argument list, and use it to immediately create an appropriate
__gc method which you attach to some userdatum guaranteed to live as
long as the coroutine does. You don't need to 
       
Does that suit your needs? If so, then your problem reduces to how to
ensure that the userdatum lives for just the length of time you want.

You could make your coroutine bodies look like this:

function body(refID, ...)
    local userdat = newproxy(true)
    getmetatable(userdat).__gc = function(self)
            luaL_unref(ThreadTable, refID)
        end
    local results = { pcall(... rest of coroutine body ...) }
    userdat = nil
    return unpack(results, 1, #results)
end

There are probably more elegant solutions (for example, one dumb thing
here is you've got two levels of pcall: first every coroutines runs
inside one, second you're explicitly invoking another one. It'd be more
elegant to find a solution that involves only one level of pcall per
thread. But this may point you in a useful direction.

-- 
Profjim
profjim@jimpryor.net