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)