[comp.sys.amiga] IPC - Another Proposal

shf@well.UUCP (Stuart H. Ferguson) (03/09/88)

IPC - Standards (Another Proposal)

(Sorry about the length of this.  Just take a deep breath... Ok, dive in... ) 

First of all, let's sumerize the problem as it now stands.  The Amiga
Rom Kernel supports an efficient message passing scheme, as well as the 
minimal tools for tasks to sync with each other.  Some programs already
use these raw facilities to pass data and commands around and the
results are exciting but only a tantalizing taste of what might be 
possible.

The real issue is how to integrate the environment.  Ideally, programs 
could use each others facilities transparently, that is, WITHOUT having 
to know any specifics about the programs they're talking to.  So
programs existing today could be incorporated into this environment with
a bit of glue, and current programs could take advantage of future
utilities not even yet imagined. 

In discussing the idea of a standard IPC, Leo Schwab made some very
valid points about why the UNIX model is inappropriate for IPC on the
Amiga, and suggested that the only solution is for programs to have
another message port expressly for "remote control." 

The problem then becomes how to standardize the command interface.  The 
ordinary approach (that is, the no-standards approach), is for each 
program to define it's own protocol and set of commands.  But, Leo
remarked, if he followed this design to its logical conclusion... 

>... I ended up with a very messy rat's nest of user
>scripts, making things unreliable.  So a free-for-all in terms of command
>structure won't work.

What is required is a more abstract communication model so that new parts
can be plugged in and old parts unplugged and the whole thing still 
operates smoothly and in a completely integrated way.  DOS devices work
this way, because an Amiga "device" is an abstract thing -- all devices
respond to certain classes of messages and are all designed to look sort
of the same.  You can read from them, write to them, or do directory
listing on them no matter what their actual implementation.  This level
of abstraction makes the system modular so that we now have recoverable
ram disks, pipes, new console devices, and everything still works in an
integrated way. 

The problem is designing a similar abstract model for interprocess
communication. 

Pete Goodeve expresses the same need when he says:
>...I suggested that we might need something more general than
>individually created links between specific programs.
>...As the whole point is to keep the system modular and adaptable,
>it would be a horrendous task to keep track of a network of ports belonging
>to the individual programs.

He describes a "message broker," which mediates requests for data and
routes the messages from those processes that are "broadcasting" to
those that are listening for that type of message. 

This is the right *kind* of idea, but the message broker as described
seems wrong.  There might end up being a lot of broadcasting going on
with little guarantee of coordinated action. 


Sill with me?  Good.

I have a proposal that addresses many of the stated problems --
modularity, integration, the requisite level of abstraction.  The design
is also open enough to provide almost limitless expansion and is IDEAL
for building an integrated hypercard or hypertext system. 

It introduces an abstraction somewhat new to the Amiga - that of an
"object."  An object is some "thing" which is a specific instantiation
of a class of similar "things."  It could be text, or a bitmap, or even
a window or a process.  It's anything for which there can be specific
instances of a general class.  For example, there can be many different
bitmaps, but they are all bitmaps, and you can do the same sorts of
operations on all of them no matter what their individual content.

The way to imagine this environment is to think of the Objects 
as being the recipient of the messages.  For example, my program could 
create an instance of a bitmap and send a message TO THE BITMAP, saying,
"BitMap, Display thyself!" and the bitmap would display itself.  The
code that did the displaying could be in another program, but that would
be transparent to my program.  If there was no tool available that could
be used to display the bitmap, the bitmap object would reply with an
error, saying, "I'm sorry Dave ..." 

Yes, you guessed it -- I've just described "object-oriented" 
programming, which is an already proven abstract programming model.  It's 
very powerful, expandable and provides a good foundation for
cooperative, message passing systems such as we're trying to develop.

So, how could such a system be implemented on the Amiga without the
overhead of some "object-oriented" designs?  Here's a first cut at an
idea: 

Have the whole scheme managed by a shared library called, say, um, pull
something out of the air ... ipc.library.  The IPCBase would contain
tables, constructed at run-time, of object classes and methods.  What 
this means is this:  Suppose that we define an object of class ILBM (I 
envision all class names and message types being four characters).  We
might have a utility program that does things to ILBM class objects.
When run, this utility program would call a function in ipc.library to
inform the library of all the types of messages that it knows how to
deal with.  For example, the program could inform the ipc.library that
it can deal with the NEW, SHOW, EDIT and PRNT messages for the ILBM
class of object.  So, the ipc.library would add ILBM to its list of
known objects and add NEW, SHOW, EDIT and PRNT to the list of messages
for objects of class ILBM.  It would also point each of these messages
at the message port for the ILBM utility program. 

Now, along comes my program.  I want to edit bitmap graphics in my
program but don't want to have to write my own editor, so I look in the
ipc.library at run time and find that the ILBM class is listed, so I
know that there is a program running somewhere that has implemented the
ILBM class of object.  So I send the ILBM.NEW message by calling a
function in the ipc.library.  The library looks up the NEW message for
ILBM objects and sends a real Message to the sleeping ILBM utility.  The
utility wakes and replies to the NEW message by creating a new instance
of an ILBM object and returning it.  My program then sends this null
object the EDIT message, and again the ipc.library looks up the
appropriate task and sends it a *real* Message.  The utility lets me
edit the bitmap graphics and replies to my program with the updated ILBM
object.  And so on. 

It is easy to define new object classes, and it is easy to define new 
"messages" for each class.  It would be possible to integrate old
programs, such as DPaint, by just writing little deamons that do the
messy work of manipulating the older programs directly in accordance
with the new standard (I know that can be done with DPaint since Live!
does it). 

The message sending interface would be standard, since it would just be
a library call in the ipc.library.  This handles the problem of getting
a "lock" on a public port -- the ports listed by the ipc.library are
valid until the owner task calls a cleanup routine before it dies. No
more Forbid()/Permit().  The things that would have to be standardized
would be the format of the message that the ipc.library sends to
cooperating programs, and the format for an "object." 

I described a standard message format earlier, but when I said,
>The basic design is derived from the EA IFF 85 standard, since that has
>worked so well and lots of Amiga users already understand it.
some politely said that using IFF was massive overkill, and some outright
laughed at me, 
>        HAAAAHAHAHAHAHAHAHAHAHAHA.......
calling it "byzantine," and "vile."  %-)

I guess I wasn't clear about what I meant.  I don't want to re-implement 
the WHOLE bloody standard, CATs, LISTs, PROPs and all, but just a part
of it. I just want to use the concept of a Chunk.  Chunks are nice
because they provide a path for expansion as well as a way of
implementing optional data fields.  The Chunk structure I was proposing
was really terribly simple and almost trivial to parse, *unlike* the
full IFF spec. 

So, briefly this time, I propose the following for standard object and 
message structures:

   struct Object {
      long  obj_class;
      long  obj_size;
      char  obj_data [ /* value of obj_size */ ];
   }

   struct IPCMessage {
      struct Message ipc_mess;
      struct Object *ipc_obj;
      long           ipc_code;
      char           ipc_data [ /**/ ];
   }

The size of the message, and therefore ipc_data, is given by a field in
ipc_mess.  Ipc_obj would point to the object that the message is
"directed at," and ipc_code would be a four-character code for the
operation requested by the message, such as SHOW or EDIT.  In both
cases, the #?_data fields would be a linear series of zero or more
Chunks with no nesting which describe the object or message.  The
possible chunk_id's would depend on their context -- that is, on the
value of obj_class or ipc_code.  Chunks always start on an even byte. 

   struct Chunk {
      long chunk_id;
      long chunk_size;
      char chunk_data [ /* value of chunk_size */ ];
   }

For the original concept that sparked this discussion -- the tools-based 
hypercard system -- object-oriented programming is *IDEAL*.  A CARD
could be a class of object and each link could be specified as a message
to another object.  One link could tell an ANIM or SMUS object to PLAY 
itself and another could just tell another CARD object to display
itself.  The possible objects would be unlimited and user-extensible,
and the individual processes to do each thing could be small since they
can ride on the power of the other parts of the system. 

I also have some really nifty ideas about how to fit this into the
Workbench, making the mild-manered Workbench more powerful than a
steaming CLI... 

So, that's the idea.  Now tell me what the problems are... :-) ;-)
-- 
		Stuart Ferguson		(shf@well.UUCP)
		Action by HAVOC		(shf@Solar.Stanford.EDU)