shf@well.UUCP (Stuart H. Ferguson) (07/15/88)
Pete Goodeve (pete@violet.berkeley.edu) writes long and thoughtfully about OOIPC and how it doesn't fit well for the kinds of things he wants to do. As official spokesman for OOIPC (:-)), I'll try to address his misgivings. | I find I'm basically uncomfortable with the "Method/Object" concept as | a general-purpose metaphor for IPC. This is partly perhaps because I | always HAVE been comfortable with the idea of independent processes | synchronized by messages passed between them (dating from well before the | Dawn of the Amiga, I should add). OOIPC is not intended as a general-purpose metaphore for IPC. The Amiga already has a general-purpose metaphore -- the Exec paradigm of messages and ports. For many applications, such as task synchronization with semaphores, the simple Exec metaphore works just fine. OOIPC does not address the entire problem of interprocess communication, just a relatively small but important part. OOIPC is targeted at the "Integrated Environment" problem that arises in a workstation-like tool like the Amiga. Although integrated environments like super-charged compilers with built-in editors and debuggers are nice and fast, the tools they provide are perhaps not the best, but cannot be changed because they are integral with the program. The Amiga, with multi-tasking and a low-overhead general-purpose IPC mechanism, makes possible a kind of integrated environment built not as a single monolithic program, but out of smaller, more general tools. The challenge, therefore, is to design a Standard Integrated Tool Environment whereby many tools can live and work in harmony and operate more or less as a single unit. Probably calling it IPC is a mistake. It should probably be called something else. | Most of the objections here, though, | arise from trying to figure out how one might implement the "slideshow" | processes I used for my demo, if the OOIPC protocol were used. Interesting that you should say this, Pete, as this is in fact exactly what I'm doing. I was very impressed with the demo PPIPC slide-show system and set about to reproduce it using OOIPC. I've been able to do it so far with a good deal of success, I think. This is not an off the wall description here -- I've actually done it and it (pretty much) works. The first major hurdle was deciding how to divide up the problem so that it takes the required form -- that of autonomous objects responding to commands. The central object class in a slide-show program is the BitMap class. The object structure I chose contains a bitmap struct, colormap and viewmode as a minimum. Objects can also have optional attributes, and some of those are used in describing special properties that a bitmap can have. For example, an optional SCRN attribute can be attached to an object and contains a pointer to an Intuition CUSTOMBITMAP Screen. I've written servers to load, delete and display Bitmap objects, as well as a server which attaches a behavior to Intuition events on a displayed bitmap. All of this is totally generic and could be used by any server wanting to manipulate bitmaps. The only part of this which was a little dicey is the Monitor method, but I think I've got that licked. The problem was how to make a bitmap sensitive to mouse clicks in a general way while still keeping it an "object," and not inextricably intertwined into the application for which it's being used. My solution was to define a method on displayed bitmaps which configures *the bitmap* so that it performs certain actions when it receives of Intuition events. These actions are to send commands to other objects. There's one more object in the system -- the slide-show object. A slide-show object has a structure containing a filename and a bitmap object for each frame of the show. Some of the bitmaps will be in memory and one of the ones in memory will be displayed. When it displays a bitmap, the slide-show server also applies the Monitor method to make the bitmap respond to mouse clicks. When the user clicks on one side of the bitmap, it will sense this and send a Forward message to the slide-show object. When the user clicks on the other side, the bitmap will send a Backward message. Viola -- the required feedback loop which also permits other types of control, via, say, a joystick client. | In the OOIPC system as currently envisaged, each server must "register" all | the method/object pairs it can service. This means that all servers must | be started up beforehand -- there seems to be no mechanism to load a server | on demand. [It's true that this is also the case with the current early | revision of PPIPC, but the LoadIPCPort command I discussed is intended to | cover this, and the user-supplied file pairing ports and servers that would | be needed to implement it is a lot simpler for him/her to handle than a | similar (though doubtless much longer) list of method/object/server | associations.] | In passing, it seems that a lot of overhead goes into making it possible to | change services (for a particular object/method pair) on the fly. Maybe | I'm not thinking of the right applications, but I can't see this feature | being needed much. [PPIPC handles the same sort of situation simply by | changing the Server on a Port.] These two are actually related, the latter making the former possible. It is possible under the OOIPC currently envisaged to have servers load on demand, not as an extension of the library but in fact as a consequence of the basic design. You do it like so: Write a "super-server" program which acts as a kind of front end for unloaded servers. The program reads from a file and registers a bunch of services that it doesn't really service, but that it knows who can. When a client makes a request for a non-loaded service, the request gets routed to the super-server. The super-server can then load the actual server and pass the message along. When the actual server starts up, it will register itself, and the services it registers will override the services registered by the super-server so that all subsequent requests go directly to the actual server. The super-server could unload servers by just signaling them with control-C (under low-memory conditions, for example), and then requests would revert to being sent to the super-server again. This approach has several advantages. It's not built-in to the IPC system so developers can write their own super-servers to fit their own needs. Also, it's transparent to client and server programmers (as it should be) -- no explicit "Load" call need be made -- and servers can be resident or loadable by user preference to tune performance with no modification to clients or servers. There are a few difficulties with the approach, specifically with startup and shutdown. How does the super-server know when a new server has started up and it ready to receive messages? There's no explicit mechanism for checking this under OOIPC, although I suppose a reasonably general one could be added. A more serious problem is how does the super-server decide when to shutdown a given server? Since there is no explicit count of clients as there is in PPIPC, there is less information about what servers are reasonable to shut down. | I foresee problems with things like Inheritance if things aren't set up | exactly right. [example of things going wrong...] Well, this would certainly be an example of something breaking because of inheritence, but then again, things will always break if you push on them hard enough. The purpose of inheritence is to extend existing classes without having to re-implement already working methods. The rules for creating a subclass are that it has to be just an extension of its super-class so that old methods will still work. If an old method will not work on a subclass then it should be overridden by a method supplied specifically for the subclass. In the example given of the FILE - IFF - ILBM class hierarchy, you probably wouldn't want to override the reading method when creating each subclass. You might want to read and IFF as if it were a FILE for example, so you could call the different methods FILE/READ, IFF/RIFF, and ILBM/RDBM. This would allow you to READ an ILBM as if it were a file, RIFF it as if it were an IFF, or RDBM it like a bitmap. Just some suggestions. | By the way, how DO you intend to specify things like filenames? [...] | In PPIPC you just use a suitable item | ('IFFP' say, instead of 'FILN') and the server will do the necessary. It's sort of the same under OOIPC. Commands have arguments, tagged by identifiers, and the server looks at those to decide what to do just like PPIPC. Using `IFFP' and `FILN' would be perfectly suitable arguments id tags for a `READ' method. The arguments are attached to the command, not the object, and are an integral part of the message, like IPCItems under PPIPC. To the Root Problem: | In my | mind, the concept "Object-Oriented" evokes expectations that don't seem to | translate well to InterProcess Communication. It's true for instance that | Object-Oriented language people talk about "Sending Messages to Objects", Hmmmm. OOIPC should not be confused with Object-Oriented Programming. It is not intended to be an object-oriented programming language. The "Object-oriented" part refers to the organizing principle behind the communication that occurs between processes. By motivating the design with concepts derived from "object-oriented" systems, messages end up having not only a standard structure, but a standard *meaning* as well. | The OOIPC concept, too, is strongly biassed towards synchronous | communication, which seems sort of strange for a message-based system. Perhaps. It's just that synchronous action is much easier to deal with in general than asynchronous action, so why not make that natural and easy to do. | Stuart has suggested some procedure calls for asynchronous operation, but | they don't mesh with the sort of paradigm I'm thinking of. He suggests | "DispatchAsync()", "CheckCmd()", and "WaitCmd()"; I assume that these are | analogous to CheckIO and WaitIO -- You are correct. That's exactly why I picked these -- because that's what's available under Exec's device I/O. I'm open to better suggestions. | This isn't an appropriate model for multiple | cooperating processes, with possibly lots of messages active: Nothing stops you from saying: replymask = (1L << ubase->replyPort->mp_SigBit); Wait (mymask | replymask); Just like you would if you had multiple asynchronous packets under Exec I/O. | It is a "two-level" system. Clients have a very different status to | Servers: Clients know about "Methods", "Objects", and "Dispatching"; | the concept of "Ports" and "Messages" is deliberately hidden [Stuart's | comment elsewhere]. Servers, though, do have to know about messages and | ports -- AND all the other stuff. I've been working from the desire to make things easy for the client programmer. My thinking has been, "There's going to be all these neat tools people will be writing to do things to bitmaps and files and all sorts of things. It would be great if novice programmers could get into the act easily and use those services without having to be experts on ports and messages and things." Server programmers I figure are going to be more experienced, and can therefore deal with the underlying structure of a Dispatch(). [Pete compares PPIPC and OOIPC from the programmers perspective] | PPIPC on the other hand is strongly Asynchronous (and much more | symmetrical vis-a-vis Clients and Servers). [...] | I think that for general-purpose IPC, hiding the Port/Message mechanism | would be a big mistake. [...] | A PPIPC example is the Script Manager for the slideshow, which only wakes | up when it gets a signal that a message has arrived at either the request | or reply Port (or a control-break interrupt has been typed -- they all | signal the same Wait() statement). [...] it is a | "Manager" -- it is WAITING for BOTH "commands" AND "responses"; there is no | asymmetry. I've written more or less the same program under OOIPC and it works just as you describe -- as both a client and a server. It uses DispatchAsync() to start the loading of a bitmap, and the synchronous Dispatch() to display and un-display bitmaps. It also acts as a server for the slide-show class object, causing it to advance or regress on command, and it also responds to control-C. It works fine. In fact, sometimes making requests synchronously with Dispatch() is more appropriate because I don't need to implement an explicit state machine to do a sequence of actions -- I just do them in order in the program. The only action I do asychronously is the one I need to do asychronously: loading bitmaps into memory. | When you have a bunch of | messages coming back at arbitrary times you have to have some way to | identify them [...] Again as an example, the Script Manager | built an internal list of the bitmaps, with a lot of extra information on | the current status of each; it was easy to add an item that was private to | the Script Manager to the message ('MARK'), directly indicating the | structure concerned. But as I understand, other servers in this setup had to know explicitly about the `MARK' item in order to correctly copy it from one message to another. If this is so, it seems less than elegant. You can add your own attributes to an object and put anything you want in them (a `MARK' attribute would be just fine), and because of the way the Object structure is designed, servers will ignore any attribute blocks they don't recognize (for upward compatability). This little tag will travel around with the object wherever it goes and never needs be looked at except by those servers (or clients) that are looking for it. | Leo's "DPaint" example brings up another point that he didn't mention | (maybe because nobody but me sees it as a problem...). A "conceptual bias" | of mine is that I see "performing a method on an object" as a unitary, | fixed operation: the idea of the method having a user-interactive component | is not intuitive to me. I don't see why. You would have no problem using a user-interactive file requester, say, by calling a function in a program: error = EditFilename (dir, name); You could just as well imagine doing this as a request to a server: error = Dispatch (editCommand, filenameObject, NULL); and using IPC (any IPC) you could do this asynchronously and do other stuff while waiting for the user to figure out what file he wants. | I agree that there is no physical problem in the way of doing this | with OOIPC (except that the sender would most likely have to suspend | activities until you were done) Not really. The sender would just have to refrain from using whatever data (or object) was passed in the message until the request completed, and this is true no matter what IPC mechanism you use. | I think [ OOIPC is ] a | fascinating concept that will have a lot of applications. I get the | feeling that we're reaching a consensus that BOTH PPIPC and OOIPC will have | their place; all I hope is that we can get some cross-compatibility so that | we don't each end up on our own island. I doesn't make sense to have TWO "standards." Either paradigm could be implemented as a sub-set of the other, it's just a question of which way is more elegant (or more Zen, as some people would say ;-). | It strikes me that as OOIPC has a defined message structure that it | actually sends to a server, perhaps all you need as a foundation for | compatibility is for this itself to be in IPCMessage format. I would suggest that the PPIPC message standard be expanded to include "objects" as a basic data type, rather than requiring all pointers to be to sized blocks of memory. This would be a much bigger step towards compatability. You were considering, Pete, adding a flag to indicate that an item pointed to another message, but why not make that a pointer to an object instead? Objects and messages are in some ways very different. Objects are like IFF files in that if a server doesn't understand something, it can safely ignore it. Messages are NOT like this in that if a server doesn't recognize some item, it should respond with an error and do nothing. Messages need to be self-describing in order to be processed by "dumb" network servers. Objects can be almost anything, since their behavior is defined by their methods. | -- Pete -- -- Stuart Ferguson (shf@well.UUCP) Action by HAVOC (shf@Solar.Stanford.EDU)
peter@sugar.UUCP (Peter da Silva) (07/16/88)
... and stirring up trouble ... In article <6524@well.UUCP>, shf@well.UUCP (Stuart H. Ferguson) writes: > Probably calling it IPC is a mistake. It should probably be called > something else. How about OO-OSE, object oriented operating system extensions. (then my idea for procedural subsets would be local OO/OSE, and seperate servers are a global OO/OSE...) > In the example given of the FILE - IFF - ILBM class hierarchy, you > probably wouldn't want to override the reading method when creating each > subclass. You might want to read and IFF as if it were a FILE for > example, so you could call the different methods FILE/READ, IFF/RIFF, > and ILBM/RDBM. This would allow you to READ an ILBM as if it were a > file, RIFF it as if it were an IFF, or RDBM it like a bitmap. I don't like this idea. Better to set up different objects of the appropriate type. Why would you want to do a FILE/READ on an object of type ILBM? There isn't any meaningful place to read into. > | I get the feeling that we're reaching a consensus that BOTH PPIPC and > | OOIPC will have their place... > I doesn't make sense to have TWO "standards." Either paradigm could be > implemented as a sub-set of the other, it's just a question of which way > is more elegant (or more Zen, as some people would say ;-). They're both Zen, but for different models. My original idea for IPC was that you would eventually be able to write programs in it, graphically, the way you can with UNIX pipelines. You just have your programs that act as generators and filters and stick them together with lines in a patch-panel sort of thing. Like if you wanted to filter an IFF image you'd have your "ILBM" icon which reads an IFF file and wraps it in a message and writes it to its output port. Your filter icon would take the ILBM and do a transform on it. Your display icon would take the ILBM and pop it up. If you wanted to edit it or save it instead you'd pop in the appropriate icons. It seems this would be easier with PPIPC, but it shouldn't be impossible with OOIPC. Why don't you two guys take a crack at it? -- -- `-_-' Peter (have you hugged your wolf today?) da Silva. -- U Mail to ...!uunet!sugar!peter, flames to alt.dev.null. -- "Running OS/2 on a '386 is like pulling your camper with an Indy car"