[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: co-routines [was Re: Unicode]
- From: Edgar Toernig <froese@...>
- Date: Tue, 06 Feb 2001 01:41:00 +0100
Roberto Ierusalimschy wrote:
> Notice that, in my implementation, a thread (or stack) is not a new type,
> and is not subjected to GC: The external code must destroy (close) it
The same as of Sol-0.42.
> (Of course, you can pack it inside a userdata, and set a GC tag method for
And this is exactly the case I meant. Each coroutine is implemented as
a userdata object that holds the state. In the first pass the userdata
is collect (but the state was still present), the gc-callback frees the
state and in the next pass the objects of the state are freed.
> > I noticed two points: you need something to pass data from one state to
> > another. Your solution with lua_ref(L1)/lua_getref(L2) is IMHO not correct.
> > You may raise an error in the wrong state.
> You have to work really hard to get an error calling lua_getref.
A Lua-stack overflow. And the error will be deadly!
> But I agree that it is not "polite" to do calls over a foreigner state.
Not only "not polite". Between two API calls (i.e. lua_getref(L2, x)
lua_setglobals(L2)) the other thread may run and you have just put him
some garbage on the stack...
> A "passvalue" function is already in my "to think" list (although I guess
> that for that case we need a "sendvalue" instead of a "receive" one).
I needed the sendvalue too. But just during the setup phase where I'm sure
a stack overflow cannot happen (the stack is new and empty). So I've
> > Another point is that I have globals for each state. At the moment
> > (with the standard API) it seems impossible to change globals for
> > other states without a new API function.
> Each thread has its own "globals". lua_setglobals operate over the
> given thread, so you can change globals as you like. (Again, you may
> need to call that function over the "wrong" thread, but again you have
> to work hard to get an error over lua_setglobals.)
Lua_setglobals cannot raise an error. But you have to get the table
to the other state. Same problem as above. IMHO that's a generic
problem. Maybe a function similar to luaD_runprotected is required to
perform a couple of operations atomically within the other state and it
will forward errors to the local state.
> > Sounds like the "Big Kernel Lock" in first Linux SMP kernels. The problem
> > was that it scaled very bad. Basically you limit the use of Lua to one
> > state at a time.
> I don't think this is really a "Big Kernel Lock". Every time Lua calls C it
> unlocks, so even a loop like «while 1 do a=sin(i) end» will be preemptive.
> (OK, you cannot do busy waiting, like «while not a do end») And, as I said,
> you can register an empty call hook, so that every function call that Lua
> makes it also unlocks; [...]
On SMP only 1 CPU may be within Lua. On single CPU systems every thread
fights for the lock and you get a thread ping pong. IMHO, it does not
scale. But maybe most people just want pthreads and do not care about
> I also like coroutines, And, using a call hook as a dispatcher, we can get
> almost "real threads" with coroutines.
As a bonus you get all this nasty locking stuff in the high level language :-)
> But coroutines block the whole program in I/O operations (yes, you
> may use select, but not always, and not for output).
Why not for output? Especially in the defined environment you find in
Lua it would be reasonable (not in ANSI-C though). And then you have
what most people call "real threads".
> Moreover (again, I agree this is sad) most OS offer an "official"
> implementation for threads, but not for coroutines.
And even more sad, the only (regular) OS I know that supports coroutines
(they call it different, though *g*) is the one I will never work with.
> Even the stack needs lock, because another thread may be doing garbage
Uh, yes, the GC would be harder. It wants to run exclusive in one thread
and wants to lock everything. You would need something to synchronize all
> And the more locks you have, the bigger the chance of subtle
> errors; and the performance gets worst too (lock/unlock are not that
Guess why I wrote "Good luck in mutex hell" once ;-) Afaik, locks
are reasonable fast as long as there's no contention. But to get
everything right is IMHO kind of masochism ;-)
I guess, a lot of people are satisfied with the single lock. I do
not need pthreads, only simple coroutines. And these seem to work
well with the interface.