|
Thanks for all that. I didn't realise that functions added to one thread are added to the global environment. Seems a bit funny, but my brain has been trained into thinking "C++" for 10 years :)
> -----Original Message-----
> From: lua-bounces@bazar2.conectiva.com.br
> [mailto:lua-bounces@bazar2.conectiva.com.br]On Behalf Of
> Julien Hamaide
> Sent: 08 June 2006 10:26
> To: Lua list
> Subject: Re: About lua_newthread
>
>
> As you know, function in lua is just a variable. When you create a
> thread, all global variable and functions from it are put inside the
> global environment, which by default is the global environment of the
> main state. So, for example, if a threads declare a global function
> Update, a variable Update is create in LUA_GLOBALINDEX table
> and is then
> available to all threads. The problem is if another thread
> create also a
> function Update, it overwrites the previous one, as the value of
> variable Update is just replace.
>
> So by creating a local environment, each thread global are not copied
> inside main state global.
> The __index tricks still allow threads to access all global
> field that
> had been registered ( such as library ). __index is triggered when a
> field is not found in current table.
>
> If you want, just make a test, create 2 script with same name
> function,
> you'll see that the function is overwritten
>
> Julien
>
> Tom Miles a écrit :
>
> > Hmmm. Previous posts on this sort of topic have stated
> that you can
> > just remove the thread handle from the stack, hence my previous
> > posts. To be honest, I'm not sure what the creation of the local
> > environment acheives? Could you explain that part for me?
> >
> > Thanks,
> >
> > Tom
> >
> > -----Original Message-----
> > From: lua-bounces@bazar2.conectiva.com.br
> > [mailto:lua-bounces@bazar2.conectiva.com.br]On Behalf Of
> Julien Hamaide
> > Sent: 07 June 2006 17:34
> > To: Lua list
> > Subject: Re: About lua_newthread
> >
> >
> > 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
> > >
> > >
> > >
> >
> >
>