lua-users home
lua-l archive

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


you might consider changing "sleep()" to something else like "lsleep()" or
similar? people might confuse if for the real "sleep( millisec )" call.

----- Original Message ----- 
From: "Bret Mogilefsky" <mogul@gelatinous.com>
To: "Multiple recipients of list" <lua-l@tecgraf.puc-rio.br>
Sent: Monday, December 10, 2001 2:03 PM
Subject: Re: ANN: sleep() patch for Lua 4.0


| Thatcher Ulrich, you're my hero.  =)
| 
| I haven't tried it, but parts of the patch look eerily familiar.  This is
| exactly the minimal behavior we need added to Lua proper to enable all the
| other wacky things people will want to do.  Let me be the first to raise my
| hand and ask that this patch be added to the core distribution.  This is
| the final piece (on top of the original rewrite to use lua_State) that
| gives programmers all the thread/task/coroutine meta-mechanisms they might
| want.
| 
| >From here it is but a short hop to the absolutely dead simple frame-based
| cooperative multitasking that game developers crave: Your program simply
| keeps a list of lua_States and calls lua_resume() on them in order each
| frame.  Put in a call to DrawMyEntireWorldAndSwapBuffers() after reaching
| the end of the list and before jumping back to the front and you're all
| set!
| 
| Further steps to enhance your use of this patch immediately suggest
| themselves, and all are done with no modification to Lua itself:
| 
| Register functions for traversing the list of lua_States (similar to
| next()).  Then you can replace or wrap the functions in the reflexive debug
| interface (section 7.4 of the manual) such that they take an extra
| parameter to indicate the lua_State you're asking about, just as the C
| versions of these functions have.  Now you have the minimal interface
| necessary to write a debugger in Lua that's capable of enumerating and
| describing all of the other lua_States as well as its own!
| 
| Register a function called fork() that takes a function and its parameters
| and adds a new lua_State ready to run it to the end of the list.
| 
| Register a function called kill() that terminates a given lua_State.
| 
| Register a function called join() that waits for a given lua_State to
| terminate and inspects its return values.
| 
| Register a function called nice() that takes a given lua_State and moves it
| around in the list, or adds it into the list multiple times.  Now you can set
| both how often and in what order a lua_State gets resumed relative to its
| peers.
| 
| Hopefully more possibilities spring to mind when you see these.  If someone
| does all of these as a library and posts it, game developers all over will
| rejoice...
| 
| 
| Thanks,
| Bret
| 
| 
| 
| 
| On Mon, Dec 10, 2001 at 11:27:22AM -0500, Thatcher Ulrich wrote:
| > I've created a patch for Lua 4.0 that makes calls from Lua to Lua
| > non-recursive (i.e. "stackless").  This allows the implementation of a
| > "sleep()" call, which exits from the host program's lua_do* call with
| > a LUA_SLEEP code, and leaves the lua_State in a condition where the
| > script can be resumed later via a call to a new API function,
| > lua_resume(lua_State*).
| > 
| > The patch is on the "Power Patches" page at lua-users.org :
| > 
| > http://lua-users.org/wiki/LuaPowerPatches
| > 
| > This is the core functionality that Bret Mogilefsky has described in
| > the "sleep()/yield() for Lua" thread, and has been much bandied about
| > in the archives.
| > 
| > As part of the VM changes, I also made it so OP_TAILCALL is properly
| > non-recursive.  This lets you implement long iteration-like
| > computations using recursive syntax (provided the compiler emits an
| > OP_TAILCALL for the tail call -- I'm not totally sure what the right
| > conditions for that are).  See the test program below for a contrived
| > example.
| > 
| > The patched lua correctly executes all the test scripts in the 4.0
| > distribution, but it's very possible there's a bug somewhere,
| > especially with error handling and such.
| > 
| > Also, these changes need to be ported to 4.1, to take advantage of Lua
| > threads.  I started with 4.0 in order to have a stable platform to
| > work in.
| > 
| > The biggest known problem with this patch is that sleep() will not
| > actually succeed if it's called from a tag method, or from a recursive
| > call to lua_do* (i.e. script calls a C function, which then calls
| > lua_do*).  Instead you get an error message and the script continues
| > execution.  So the semantics of sleep() depend somewhat on the
| > internal workings of the interpreter.  For practical use in a game
| > scripting language, this shouldn't be a problem.
| > 
| > Feedback welcome!
| > 
| > -- 
| > Thatcher Ulrich <tu@tulrich.com>
| > http://tulrich.com
| > 
| > 
| > 
| > ------ test/sleep.lua -------
| > -- test the sleep patch.  The sleep patch adds a sleep() function,
| > -- which suspends script execution in a restartable state (via the API
| > -- function lua_resume(L)).  The sleep patch also implements true tail
| > -- recursion for the OP_TAILCALL opcode.
| > 
| > 
| > function donothing_tailrec(x)
| > return x
| > end
| > 
| > function donothing_rec1(x)
| > return donothing_tailrec(x)
| > end
| > 
| > function donothing_rec2(x)
| > for i = 1,1000 do
| > donothing_rec1(x)
| > end
| > return donothing_rec1(x)
| > end
| > 
| > function donothing_rec3(x)
| > for i = 1,1000 do
| > donothing_rec2(x)
| > 
| > -- exit script execution, returning LUA_SLEEP to the caller.
| > -- The caller can resume the script via lua_resume(L).
| > sleep()
| > end
| > return donothing_rec2(x)
| > end
| > 
| > c = clock()
| > r = donothing_rec3(10)
| > t = clock() - c
| > print("time = " .. t .. ", result = " .. r);
| > 
| > 
| > count = 0
| > 
| > function increment_tailrec(ct)
| > -- stupid recursive function to increment 'count'
| > if ct <= 0 then
| > return 0
| > else
| > count = count + 1
| > return increment_tailrec(ct-1) -- for some reason, we must return a value for OP_TAILCALL to be generated.
| > end
| > end
| > 
| > 
| > function test(x)
| > count = 0
| > increment_tailrec(x)
| > if count == x then
| > print("success --> count = " .. x);
| > else
| > print("failure --> count = " .. count .. " but x = " .. x);
| > end
| > end
| > 
| > 
| > -- The sleep patch also implements proper tail recursion for the
| > -- OP_TAILCALL opcode.  In unpatched Lua 4.0, one of the following
| > -- calls will probably cause a stack overflow error.
| > test(1)
| > test(10)
| > test(100)
| > test(1000)
| > test(10000)
| > test(100000)
| > test(1000000)
| 
| -- 
| Bret Mogilefsky * Mgr. SCEA Developer Support * mogul@gelatinous.com
| 
|