[MUD-Dev] Re: PDMud thread summary

Chris Gray cg at ami-cg.GraySage.Edmonton.AB.CA
Sun Oct 25 14:49:23 New Zealand Daylight Time 1998

[Niklas Elmqvist:]

General comment: thank-you - something I can sink my teeth into, and get
an idea of what you are talking about.

 >class Pipe {
 >	virtual Msg *Recv(ModuleID hCurr); 

 >class CallPipe : public Pipe {
 >	virtual void Recv(..)

Oops - change in declaration there. I'll assume the second Recv should
have the same prototype as the first.

 >Okay. What I have in mind is this: Say we have a running system with one
 >module loaded, call it A. A belongs to the ParserModule class which has
 >been subclassed outside of the executable (external inheritance) and
 >dynamically loaded into the running MUD.

OK. I *think* I've seen descriptions of "external inheritance", so I'll
ignore it for now. However, if I am understanding correctly, doesn't using
this technique preclude using any implementation language other than C++,
(and that everyone use the same C++ compiler) since external inheritance
requires consistent object layout and virtual function table format? How
would modules written in the MUD-language match this layout? The MUD-language
and virtual machine could force all entities manipulated by the MUD-language
to inherit from whatever base class is the one chose for the external
inheritance level. Isn't that kind of restrictive? The net result of
this, is "just another C++ MUD" isn't it? If that base class is changed
in any way, *everything* has to be rebuilt, possibly including all
MUD-language code. Wouldn't that completely invalidate any existing
database? What are the benefits that balance these downsides?

I'd like to see databases portable from system to system. E.g. one
created on say, a SPARC UNIX box is directly usable on an X86 WIN32 box.
Since MUD-language code is likely stored in that database, it should be
similarly portable.

 >Module B is loaded in some way (signal or command). B belongs to the
 >SocialModule class, also externally inherited from the core. What happens
 >is this:
 >1. The module manager takes charge of the situation. The shared lib is
 >	opened using dlopen() (depending on OS, of course).  
 >2. The executable extracts a pointer to the factory function in the lib
 >	(yes, it has to be there) using dlsym().
 >3. The executable calls the function, passing it a pointer to the Core
 >	class. This is the basic set of primitives the module may access.

Is that a pointer to a Core object, rather than class? I thought C++
classes had no externally visible representation.

 >	The pointer is passed to the constructor of module B (see class
 >	Module) and the function then returns with the new pointer to
 >	the module B object. 
 >4. The module manager adds the new module object to a list.
 >5. The executable calls B->Init() (that is SocialModule::Init()) and
 >	passes it its new ModuleID.
 >6. The Init function, which is written specifically for the SocialModule
 >	(it is virtual and overrides the original Module::Init()), does
 >	some initialization and then decides it needs to talk to a parser.
 >	It calls Core::Broadcast() along with a generic status message ("I
 >	am a CommandHandler")
 >7. Object A (the parser module) receives this message on the broadcast
 >	channel/pipe and decides that it is interested in CommandHandlers.
 >	It calls Core::GetPipe() with the ModuleID it received from the
 >	Message.
 >8. The intermodule communication manager (CommManager) receives the
 >	request and queries the module manager about the location of the
 >	two ModuleIDs. If on the same system, it creates a CallPipe
 >	(function pointers). If multi-threading is required, it creates a
 >	QueuePipe, and so on. It returns the pipe to the calling module
 >	(A).
 >9. Module A receives the pipe and immediately calls B on it, telling it
 >	that it is a parser and wants a command grammar and a way to
 >	package data for passing it.
 >10. Module B provides A with this and then sits idle until information
 >	from A comes through the pipe.

This all sounds pretty good to me, but I'm a bit unsure of some of your
basic assumptions. Are you assuming in '10.' that each module has its
own thread? Are you assuming there can be only one parser module loaded
at any given time? If so, what happens when more than one does step 7.?

It also sounds like some of the things that have been discussed before
are assumed. E.g. in order for your 'CallPipe' to work, the prototype
used for a given kind of communication must be pre-determined. I'm
still pretty unsure of the flow of control with such a setup. If all
modules have a thread, then it is clear that they just sit awaiting
something on one of their data-copying inputs. If not, I'm much less sure
of this. As I mentioned before, I think there is a good chance that some
modules (e.g. socket input) would want to have multiple threads, and that
the processing of those inputs, all the way through the system, is what we
would like to happen potentially in parallel on a big SMP.

 >I haven't ironed out any details, as you can tell, and most of this I made
 >up as I went along. It may therefore be totally demented; I make no
 >guarantees. But hopefully, it will help in seeing what I envision.

Yes, it helps, thanks!

Chris Gray     cg at ami-cg.GraySage.Edmonton.AB.CA

More information about the MUD-Dev mailing list