lua-users home
lua-l archive

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




On Tue, Dec 1, 2009 at 6:37 PM, Jim Pryor <lists+lua@jimpryor.net> wrote:
On Tue, Dec 01, 2009 at 03:07:13PM -0800, Chris Gagnon wrote:
>    I need to clarify i suppose, I did/do not intend to access the thread from
>    the co routine.
>    I only am trying to decide how best to get my refID in the cleanup
>    situation.
>
>    Imagine the code:
>
>    int iRet = lua_resume(pLuaState);
>    if (iRet != LUA_YIELD)
>    {
>        // the thread is dead, must unref it to let GC do it's job.
>        // how do i get the refID?
>    }
>
>    What I'm trying to avoid is having some c side map between lua state
>    pointers and ref id's.
>    It make little sense to me that i can't somehow store that along with the
>    co routine so that i can avoid the lookup and management of that variable
>    size data structure.
>
>    This is why I tried storing the refID on the co routines stack.
>    However was thwarted by errors in the lua script leaving the stack in a
>    function scope such that i couldn't get my value.
>
>    After your response I tried a weak key table with both the key and value
>    being the thread, in this way i could set the thread to nil and GC would
>    do the rest.
>    This was also thwarted by errors, since the only way i can see to push a
>    thread onto the main state stack to set it nil in the thread table, is to
>    call pushthread on the co routine(which is dead hence the problem) and
>    then move it to the main state stack.
>
>    I don't understand why the c api dosn't support:
>          lua_pushthread(L, LThread)
>    but i'm not out to change lua so this is only a curiosity.


I see, so you're not actually using the refIDs to lookup the threads,
just to keep them alive.
Nope  :o)

I don't have much experience working with threads C-side. Are you sure
that lua_pushthread(LThread) won't already do what you want? If L is the
state in which LThread was created, doesn't lua_pushthread(LThread) push
LThread onto L's stack? Does it really push it onto LThread's own stack?
I agree that the API looks to be either confusing or incomplete here.

From Lua 5.1 Manual

lua_pushthread

int lua_pushthread (lua_State *L);

Pushes the thread represented by L onto the stack. Returns 1 if this thread is the main thread of its state.

Unlike most pushes that are like:
    void lua_pushtype( lua_State * L, type t)
the push thread function dosn't take enough parameters to know what stack to push the thread onto.
incomplete? or some sort of protection against introducing a potentially bad lua_state * into lua?
The later makes the most sense to me.
 

If you could rely on LThread to return without errors, then you could
pass the refIDs to LThread on thread start, and return them on exit. But
you say you can't rely on that.
 
In our environment i need to recover gracefully when non-programmer types mess things up, so i definately cannot rely on their scripts. ;o)


Then why not create a struct that has a slot for the refID and a slot
for the LThread, and pass that around between your functions, rather
than the LThread itself? Then:

   int iRet = lua_resume(pMyStateWrapper->state)
   if (iRet != LUA_YIELD)
   {
       // push pMyStateWrapper->refID onto stack, unref the ThreadTable
       // for that refID, and let GC do its thing on the thread..
   }

That seems too simple, I'm guessing you have some reason for avoiding it
but I don't see what it is.
 
My reasoning for avoiding this is that when a lua script calls a cfunction that may yield the signature is:
    int function(lua_State *L)
so to store this for a resume later on i would need to find the pMyStateWrapper somewhere.
Now I'm back to looking it up in a map somewhere which is what I'm trying to avoid.

If thats the case i mine as well do it when the coroutine dies, this happens less often the yields.


--
Jim Pryor
profjim@jimpryor.net

I really appreciate the feedback.

Really creating that map and management code could have been written in less time then I've already spent trying to find a way to avoid it.  I just seems like it shouldn't be necessary but every way I've attempted to get around it has failed miserably.

Maybe I'll bite the bullet and just create the map, but i won't sleep well because of it.
More feedback would be great! I thirst to understand.

Cheers,
Chris