[MUD-Dev] Re: TECH: Distributed Muds
J C Lawrence
claw at 2wire.com
Thu Apr 26 23:07:21 New Zealand Standard Time 2001
On Thu, 26 Apr 2001 21:18:11 -0700
Caliban Tiresias Darklock <caliban at darklock.com> wrote:
> On Thu, 26 Apr 2001 20:31:37 -0700, J C Lawrence <claw at 2wire.com>
>> I've never liked the base concept of a select() looping process
>> that tried to do real work between select() calls. It can work
>> to be sure, but it has always smelled of playing with fire.
> I've always seen it as sort of an "every other MUD does this, it
> must be a good idea" solution. I think most people who start
> writing a MUD server concern themselves first and foremost with
> making a good *MUD* instead of with making a good DB core, a good
> object model, and a good communications link.
I'd always thought that it was because that's been the basic model
discussed in Stevens and Comer, and its also the simplest to
incrementally develop and extend.
Path of least resistance and all that rot.
> Don't mention this communications model on any kind of network
> programming forum, though. You'll never hear the end of how stupid
> you are. ;)
I have the scars.
>> I prefer having a thread dedicated to socket IO, pulling in and
>> buffering the IO as received, and then handling compleated blocks
>> off to one or more queues (depends on whether you do pre-sorts)
>> for the other game systems to pick up and process appropriately.
>> There are several advantages, not the least of which is that you
>> decouple your command/entry model from your processing model.
> That's pretty much what I consider the "ideal" model, myself. I
> don't do it, because I'm still not entirely comfortable with
> threads, but I'm working on getting there. Currently, I still use
> select() for I/O, just because... well, every other MUD uses
> it. :P
I used to use thread pools until I figured out I was nuts.
My current model is a thread that just spins on select, grabs the
packets and uses them to incrementally build command strings (one
per socket). When a command string is compleat (its framed) it gets
taken out of the pending pool and moved on over to a queue (simple
counting semaphore lock to control/serialise access). The rest of
the game (in the simple case) then sits off in another thread and
pulls command messages off the same queue using the same counting
semaphore for access locking to the queue structures. Sitting under
this is a light weight custom heap manager which looks something
I have a large pool of buffers to use for command strings.
On the IO thread there's a static array of pointers to command
strings. As data arrives its just appended to the end of whatever
buffer is pointed to by the N'th array member, where N is the
On command compleation the array pointer is atomically moved from
its current buffer to free buffer from the pool, and a node is
pushed on top of the FIFO (also custom heap, same style), wbich
points at the now compleat command string.
On the game side a node is popped from the FIFO (single linked
list), the FIFO node is freed (recycled back into the pool), and
the command string is processed.
As soon as the command string is processed, it is freed by
flagging it as unused back in the buffer pool such that the IO
thread may not pick it back up to put in the array and begin all
Translation: The IO thread is blocked 99.99% of the time. The
contention rate on the FIFO is present but minimal, and could be
nearly entirely avoided through careful construction of the FIFO
control structures (if you can assume that pointer assigments are
atomic on your platform).
Small, simple, well constrained threads that perform well known and
exactly defined tasks with clearly understood interfaces and
contracts with the rest of the world. I like that approach. I'm
not fond of the general purpose does-a-lot-of-things threading
approach I see so often.
J C Lawrence claw at kanga.nu
--=| A man is as sane as he is dangerous to his environment |=--
MUD-Dev mailing list
MUD-Dev at kanga.nu
More information about the MUD-Dev