lua-users home
lua-l archive

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

Hi Slime:

Actually I just had an article published in Game Programming Gems 5 that
deals with this issue.  While don't think I can post the code verbatim here,
I can give you an outline.

First, the term "thread" is used a bit differently in the LUA documentation
than most people are used to.  Essentially, a thread is a new lua_state that
you have created.  It maintains its own "instruction pointer" and stack so
it can yield and resume independently of other "threads".

I create two types of C objects to manage all this: a single manager object,
and a "thread" object for each thread (really child-state) that I have

A "thread" object (in a somewhat poor choice of words, I called this object
a "script" in my article) creates an actual Lua state with lua_newthread().
This state can then run code, yield and resume independently of other
states/threads.  The object also maintains few timers and flags that can be
set by script code which help the manager control when to re-activate the
thread after a yield.

The manager object keeps a list of all "threads" you've created.  Each frame
of your game, it checks each thread to see if it needs to be resumed.  Often
based on a timer, or some flag that it is waiting on.  If a thread is
resumed, it executes all its Lua code up until the next script command that
causes a yield().  This command sets the correct timers and flags which
instruct the manager how and when to resume the particular thread.

I have routines like WaitSec(), WaitForTime(), WaitForFlag() that yield the
given state and tell the manager to resume it when the given conditions are
met.  I even keep a set of "global" flags that all states/threads can see.
This lets one state/thread cause another to resume execution.

There are a few complexities involved with all this, but hopefully it will
get you on the right track.  Once you get it working, Lua becomes an
amazingly powerful and easy way to extend your game.

-----Original Message-----
[] On Behalf Of John Haggerty
Sent: Monday, March 07, 2005 8:45 PM
Subject: Threads vs Coroutines and Wait()

Hi, I'm a new user of Lua and, as usual, I'm trying to use it as a scripting
language for my game.

I want to have a Wait() function which takes a length of time and "pauses"
for that time. Of course, during this time, gameplay must continue, so what
really needs to happen is the script has to stop executing, and be resumed

I figured I'd use coroutines to do this. Wait() could tell the game engine
to resume the current coroutine in X seconds, and then yield. Gameplay would
continue, and the game engine would later resume the coroutine.

But a problem occurs when the script writer starts using coroutines on their
own. If they create a coroutine and run it, and then *that* coroutine calls
Wait(), then it will yield back to their own original coroutine rather than
all the way back to the game engine.

I was hoping that using "Threads" as described in 3.20 in the documentation
might avoid this problem, and that lua_resume/lua_yield doesn't take Lua's
coroutine.resume() and coroutine.yield() into account. But after reading
some messages in this group I'm worried that lua_resume and lua_yield are
essentially identical to coroutine.resume() and coroutine.yield(), so my
problem remains.

Is there any way to achieve what I want? Is there any sort of tricky usage
of coroutines that avoids the problem, or is there a solution that doesn't
involve coroutines at all? Or will I have to require that the user not call
Wait() from within a coroutine (and can this be automatically enforced)?

Thanks for any help or explanation you can offer. Sorry if I've unknowingly
violated any unwritten community rules, as this is my first post here. =)

(As a side note, why does 3.20 talk about "Threads" while 2.10 talks about
"Coroutines?" Is there a difference or is it just a different name depending
on whether you're calling the functions from C code or from Lua?)

 - Slime
 [ ]