[MUD-Dev] Event Handling

Jon A. Lambert jlsysinc at ix.netcom.com
Mon Jan 12 22:37:04 CET 1998


On  6 Jan 98 at 17:03, JC Lawrence wrote:
> On Mon, 5 Jan 1998 09:10:52 PST8PDT 
> Vadim Tkachenko<vadimt at 4cs.com> wrote:
> > Jon A. Lambert wrote:
> 
> >> Variations on event-driven design
> 
> > Can you please elaborate on that?
> 
> There are a couple base models going about the list.  Jon and I have
> some of the more intricate designs.  I'll let Jon describe his.
> 

Alrighty!  A request to delve back into the low-level nitty gritty details. 
I posted some definitions in another message and I won't elaborate on them 
here except to state that event-driven systems may be single-threaded or
multi-threaded.  They may even be soft-threaded (cf. Cynbe ru Taren's MUQ). 
This is rather obvious since ColdX, MudOS and some others implement 
mechanisms for event processing.  They are hybrids of the procedural and 
event models.  

JC's model and my own are hybrids of all three models, but at the language 
or mudlib programming model they will likely exhibit the traits of a 
concurrent processing model. Invariably we touch on threads and data 
concurrency/consistency that one might serialize and largely ignore in a 
single-threaded event-driven system.  So...here is how I stand right now... 

> To describe my system loosely, and briefly:
> 
>   The server is heavily multi-threaded (I think the idle-state is over
> 50 threads currently).
>

My model currently has a fixed pool of threads and is strongly 
partitioned and layered.

    Network subsystem - 1 thread to listen for connections and
          1 thread per connection.   Threads are created and destroyed
          as needed.  May be a good candidate for pooling later...
    Dispatcher - 1 thread - pops events off the queue and places in proper
          Executor class. 
    Executor - 6 threads - 3 for normal activity, 1 real-time monitor
          thread, 1 low-priority and 1 lazy priority(*) thread    
    Object manager - consists of 4 threads , Lock subsystem, Cache 
          subsystem, Database subsystem and Logging subsystem. 

>   All events are processed aynchoinously and in parallel.  
>

Nod.  'cept mine are asynchronous. :P
 
>   The server is lockless.

I do object locking.  My model is based on IBM's DB2 which will attempt to 
spin-lock an object.  A lock is attempted several times for a brief 
duration (milli-seconds).  If failure occurs, the event is rescheduled.  
Logging is very very DB2ish also.  The primary purpose of logging is
recovery from literally pulling the plug and insuring backups maintain
data synchronization. 

>   I don't guarantee order of execution of two unrelated events.
> 
>   The base design:
> 
>     Events are logged with the Dispatchor in the Event List as a tuple
> of an object:method call, various arguments, various ownership data,
> and either a state time the event is to start execution, or a
> percentage chance value that the event will start execution within any
> given minute.
>

Similarly I keep Object:method and parameter stack, the event state time 
and an event class (0-3) indicator - 0 is monitor class, 1 is normal class, 
2 is low-level and 3 is lazy priority.  (*)Lazy priority threads bypass all 
object locking read or write, they simply do not care about data integrity. 
This is used for low-level SIM processes, which do tallying of current 
state.  My event queue object is ordered at insert.

>   The Dispatchor procresss the Event List, sending ripe events to the
> Executor.
> 
>   The Executor receives the ripe events from the Dispatchor and stores
> them in priority order in teh Event Queue.
>
>   The Excutor processes the events in priority order by handing them
> for processing to to the Event Pool, a dynamically sized pool of
> threads.
> 

I'm a bit different here also.  The Dispatcher places the event data in
the appropriate Executor data area and starts the Executor thread.  
Executor threads will generate events which are inserted into the Event 
queue by the executing thread. 

>   Events that fail to commit are rescheduled with the Executor at a
> different priority.
>

Nod. My priority does not change however, the state time is incremented.
 
>   Event's have no effect upon the DB or state until and unless they
> commit.
> 

Upon an executor threads successful termination pointers are swizzled in 
the cache and locks are freed.  Upon unsuccessful termination locks are
freed.  Each event is equivalent to a application consistent transaction.  
The Object cache contains two copies of objects (before/after) when write 
locks are requested.

BTW, I have flipped my language model around.  Instead of writing 
specialized _event_ methods, I have two forms of method calls.  One will
cause the method to be immediately invoked, the other schedules the
call as an event w/time and class.  Seems to make lib programming much 
easier.  Also, I have given up all attempts to pre-bind methods at compile 
time to the objects they may be interested in (a way of pre-locking at 
execution start up).  The dynamic nature of the object requests makes this 
just silly.

Comments, criticisms, or vicious personal attacks welcome. :)

--
Jon A. Lambert
"Everything that deceives may be said to enchant" - Plato



More information about the mud-dev-archive mailing list