lua-users home
lua-l archive

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


The problem with this approach is that the thread will never be garbage collected as lua_newthread push a thread handle on the main thread stack.

So at the end of this call, you still have the thread handle on the stack.

I also see that you use the global table to store thread function. Pay attention that if 2 thread have functions with the same name, they will collide.

I use same kind of thing for a game, this is my approach for both liveness of thread and local space :

In my Thread constructor :
// master state is my main thread
   ThreadState = lua_newthread( master_state );

   // prevent thread from being garbage collected
   lua_pushvalue( master_state, -1 );
   ThreadReferenceIdentifier = luaL_ref( master_state, LUA_REGISTRYINDEX );

//Create a local environment with a link to global environment via __index metamethod
   lua_newtable( master_state );
   lua_pushvalue( master_state, -1 );
   lua_setmetatable( master_state, -2 ); //Set itself as metatable
   lua_pushvalue( master_state, LUA_GLOBALSINDEX );
   lua_setfield( master_state, -2, "__index" );
   lua_setfenv( master_state, -2 );
   lua_pop( master_state, 1 );

and in the destructor :

luaL_unref( master_state, LUA_REGISTRYINDEX, ThreadReferenceIdentifier );

If you have any questions about it, don't hesitate

Julien Hamaide
Lead Programmer
10Tacle Studios Belgium


Tom Miles a écrit :

Thanks for the speedy response.


>> Can you show us how you initialize your thread??

I am using an approach similar to the one in Game Programming Gems 5, where I have a manager object that controls the main state and dishes out threads when requested. I.e.

//
static void CreateThread(State & state)
{
        if (m_MainState == NULL)
        {
                m_MainState = luaL_newstate();
                luaL_openlibs(m_MainState);

                luaL_openlib(m_MainState, "Script", scriptLib, 0);
        }

        state.m_state = lua_newthread(m_MainState);

// save a pointer to the thread manager object in the global table
        // using the new thread's vm pointer as a key
lua_pushlightuserdata(m_MainState, state.m_state); <--- Is this causing a problem?
        lua_pushlightuserdata(m_MainState, &state);
        lua_settable(m_MainState, LUA_GLOBALSINDEX );
}

static void ReleaseThread(State & state)
{
        int stackSize = lua_gettop(m_MainState);
        for (int n=0; n<stackSize; ++n)
        {
// This check should be: lua_isthread() && lua_tothread() == state.m_state
                if (lua_touserdata(m_MainState, n) == state.m_state)
                {
                        lua_remove(m_MainState, n);
                        break;
                }
        }
// For the time being, set the value of the key (the state we are removing) in our map to be nil
        lua_pushlightuserdata(m_MainState, state.m_state);
        lua_pushnil(m_MainState);
        lua_settable(m_MainState, LUA_GLOBALSINDEX);

// There is also code to close down lua if we have released the last thread here
}

>> If you use a weak value table, the entry will be deleted when the object
>> is collected.

>> Just put "v" in field __mode of the metatable of your table. If you want
>> weak key, just put "k".

As you can see, I am using the globals table, but I suppose I could create a weak table especially for the job instead.

> Tom
> > -----Original Message-----
> *From:* lua-bounces@bazar2.conectiva.com.br
> [mailto:lua-bounces@bazar2.conectiva.com.br]*On Behalf Of* Raymond Jacobs
> *Sent:* 18 May 2006 16:20
> *To:* Lua list
> *Subject:* Re: About lua_newthread
>
>     When you are done with a thread (when lua_resume returns and it's
>     not a yield), you should remove the thread directly from the
>     stack, this will remove the reference to it and it can then be
>     garbage collected (its a pain I know =/).
> > another method which I've not yet done but should work, is to
>     create a new thread, create a lua reference to it (using lua_ref)
>     then pop it off the stack immediately (so it doesn't get buried),
>     and later when you are done with it, destroy the reference
>     (lua_unref) and that should allow it to be GC'd
> > hope that helps, > > Raymond Jacobs
>     Owner,
>     Ethereal Darkness Interactive
>
> > On 5/18/06, *mos* <mmosquito@163.com <mailto:mmosquito@163.com>>
>     wrote:
>
>
>         Hi
>
>         in lua5.1 manual:
>
>         lua_newthread
>                  lua_State *lua_newthread (lua_State *L);
>         There is no explicit function to close or to destroy a thread.
>         Threads are
>         subject to garbage collection, like any Lua object
>
>                I don't understand this , for example like Npc in a game
>
>                function AI()
>                        while(true) do
>                                walkto(A)
>                                walkto(B)
>                                ...
>                                walkto(Z)
>                        end
>                end
>
>                I bind each npc with a lua_State by lua_newthread
>
>                but the npc will die and i should close the lua_State ,
>         but I can
>         not.
>                what can I do ? or some better suggestion ?
>
>         Best Regards
>         mos
>
>
>