[MUD-Dev] Re: PDMud thread summary

Niklas Elmqvist d97elm at dtek.chalmers.se
Mon Oct 26 00:05:39 New Zealand Daylight Time 1998


On Sun, 25 Oct 1998, Chris Gray wrote:
> [Niklas Elmqvist:]
>  >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. 

Thanks, I needed that :) And sorry. I guess I must sound sort of obsessed.
I'll be quiet on that issue from now on. 

> 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?

Yes, it does. It works since the compilers I've come across don't do
anything funky with the virtual function tables of subclasses.

> 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. 

Hmm, not sure what you're getting at here, but yes, the base class in the
executable must be made adequate since it must be used for all accessing
of the objects (at least on the driver level). And are we sure we will
support MUD-language code modules on this level? IMHO, MUD-language is
better suited to in-world stuff.

> Isn't that kind of restrictive? The net result of this, is "just another
> C++ MUD" isn't it? 

Yes, but the alternative would be "just another C MUD", or what? Do you
refer to some specific phenomenon?

> 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? 

Well, my thinking is that external inheritance (sorry) would only be used
for modules and events -- I've been concerned mainly with the driver level
here. The database module(s) would build and use their own data
structures, and would not be affected by any change in the base classes.
Actually, trying to tie in database structures into the core would
needlessly narrow our options.

> What are the benefits that balance these downsides? 

I think I've gone over some before, but the main reason I see is that this
is a neat way of using O-O concepts over shared lib boundaries with all
that entails. AFAIK, there does not exist a good mechanism for exporting
classes in shared libs. With this technique, we can have encapsulation,
polymorphism and inheritance all working the way we want them even though 
our main functionality may be imported in dynamically loaded modules.

Of course, since my scheme has met with some (!) resistance, I guess that
this is one vision I'll have to abandon. :) But why don't someone else
describe their own view at the DevMUD architecture and perhaps we can all
meet in the middle? (Yes, Chris Gray's thoughts have been duly noted :)

> 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.

Again, nothing in the core should affect anything in the databases. Sure,
the modules are themselves dependant on the base class in the core and
they all use inherited versions of the event class, but this does not have
an impact on the database. 

>  >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.

It is a pointer to the Core object, of course.

>  >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? 

Hmm, no, I am saying that it will not be called at all until a message
propagates to it (understand that my own project is single-threaded, and I
have little experience with multi-threading). All modules are dormant
until they are called into play by an event -- this is the only way of
having work be done in the server. Of course, some modules will be woken
quite a lot by periodic events; the network I/O code would schedule its
own wake-up event in the Init() function and thus be called every so
often.

> 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.? 

No, I don't think I am assuming that. The individual parser modules need a
way of knowing if a command handler is applicable to their mode of
operation, and will thus decide at step 7 if they want to get in touch
with the module. If both want to, then fine! The command handler will get
two parsers sending it commands.

> It also sounds like some of the things that have been discussed before
> are assumed. 

Yep, but as I said at the top of my message, this were *my* own thoughts.
I am not saying we should use them (although I think it would be nice if
at least we were influenced by them), I only wanted to clarify a few
things about them. 

> E.g. in order for your 'CallPipe' to work, the prototype used for a
> given kind of communication must be pre-determined.

Yes, but since we will call some sort of structure here, the prototype can
be fixed to void IMCCall(Message *hMsg) or something. The Message class
can be subclassed to provide specific functionality. This is also where I
was talking about having the innards of Message be serialized if needed.

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

-- Niklas Elmqvist (d97elm at dtek.chalmers.se) ----------------------
  "The trouble with being a god is that you've got no one to 
   pray to."
		-- Terry Pratchett, Small Gods





More information about the MUD-Dev mailing list