On Mon, Nov 30, 2009 at 11:07:36PM -0500, Jim Pryor wrote:
> 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.
I find the example the way you've described it somewhat bewildering. Why