[Mono-devel-list] Embedding Mono in a Virtual World

Tim Fries timf at dicecorp.com
Fri Jan 28 18:31:00 EST 2005


> How did you implement the cooperative multitasking?

Every thread of execution has a private System.Collections.Queue that
contains work items -- basically a delegate with some extra administrative
data, and an AutoResetEvent that the thread can WaitOne() on when the Queue
is empty.  There's a rudimentary event system that is basically a sorted
ArrayList that dictates what the timeout on the WaitOne() should be.

The work items it executes are simply designed to execute fast; anything
that might possibly block is done asynchronously, with notifications punted
back to the main thread for handling.  Pretty much just a straightforward
implementation of the third C10K strategy[1].

(I'm also pretty sure this is how RunUO, a multiplayer virtual world server
written in C#, works.)
 
> Yes, it's a shame the MUD-Dev archive is broken at the
> moment. Do you have any specific references for things
> I should look at?

I don't really have anything to point you at as far as that goes,
unfortunately. Like I mentioned, I haven't tackled user code myself; and I
have a feeling I'll opt for a pragmatic approach rather than an academic one
when I do. (I'm currently worked on a centrally-controlled world where user
code isn't even allowed, but the benefits of hot scripting will eventually
justify its inclusion.)

My experience with MUDs is that they, in some form or another, just hoist
the restrictions of the cooperative multitasking model directly on end user
coders. They don't provide anything that can block; they force the user to
hook up to event callbacks invoked by the underlying world rather than
letting them enter any sort of long-lasting loops, etc.  Various provided
functions have costs associated in CPU time, and they charge the user a
corresponding amount of "pennies" (or the local equivalent) -- which are
basically doled out to users in regular intervals by the system; as a method
of restricting how much load a single user can place on the world.

If a user can't afford to a resource-intensive function; their script just
stops executing; no harm, no foul.

> > interpreting/compiling as a state machine that you
> > can enter and exit at will would probably solve 
> > that problem well enough.
>
> Which sounds like Paolo's second suggestion.

I've done a bit more thought on this since it was first mentioned, and I
think I'm coming to the realization that maybe this isn't the best idea:

The main problems with it is that it's a rather daunting task to implement
(you're now building a compiler in addition to a world), and seems to make
it infeasible to guarantee deterministic behavior to the users.

Since their code is effectively preemptively multitasking (from the point of
view of the script author, anyway), they're going to have to be mindful of
all the same multithreading and locking problems that you'd have to if you
stripped off the extra layer of indirection.  One script "thread" may be
tweaking properties of an object in response to a user's actions on it,
while another is simultaneously moving it to someone else's possession!

Pushing the cooperative design down onto the users like MUDs have, in my
experience, just eliminates these problems; and helps you guarantee that the
world is in a known state at every point in execution.  The main expense is
probably just the event-based environment that users will have to script in.

You may want to take a look at Lua.  It's used often for embedded scripting
of this sort; provides nice callbacks to restrict expensive function calls,
or if it just plain runs longer than you want it to.  There's a LUA.NET
project as well, but I don't think it's made it out the door yet.


[1] - http://www.kegel.com/c10k.html#aio




More information about the Mono-devel-list mailing list