Nuclear Instruments and Methods in Physics Research A293 (1990) 347-351 North-Holland
347
AN OBJECT-ORIENTED COMMUNICATION PROTOCOL Lee J. CHAPMAN Fermi National Accelerator Laboratory *, P.O. Box 500, Batavia, IL 60510, USA
OOC is a high-level (OSI application layer and above) controls communication protocol . While natural languages are too complex for the controls environment, computer protocols are often insufficiently expressive . OOC is an attempt to balance simplicity and expressivity, and is sufficiently flexible to express data aquisition, control requests, alarm messages and error messages in a straightforward generic way. OOC supports dynamic creation of objects. It can be used in networks, for intertask and even for intratask communication . OOC, the protocol, is supported by OOC, the code, written in portable C . The lower level of this code supports a tagged-data scheme, with tags as elementary as INTEGER and BOOLEAN and as complex as OBJECT and MESSAGE. These tagged data can be evaluated in a LISP-like way .
1 . Introduction My basic vision of a control system is as a sea of objects spread over a computer network, organized logically and somewhat independently of the physical organization of the network. That is, any particular processor might contain one or more logical groups of objects, and an object group might be spread over multiple processors. These objects send each other messages in a simple, uniform way, regardless of whether the objects are nearby (e.g . in the same processor) or distant (e.g. on a different network node) . These messages constitute control, data aquisition, alarm reporting, and more esoteric functions such as creation of new objects and interrogation about each other's capabili-
ties . Objects are very well suited to control systems . They can be used to represent individual physical components of the accelerator, such as power supplies and valves, as well as components of the control system itself, such as terminals. Objects can also be used to represent concepts such as groups of components (e .g . a collection of power supplies) or types of components (e.g . the very notion "valve"), as well as totally abstract entities such aç FIT) control loops and finite-state machines. Ultimately, the very concept "object" is itself representGd as an ovjwt! All of these things need to be talked about in a control system, and many c f them need to talk to each other. As objects, tney can do so by sending messages and receiving replies. As cbjects. they contain within
* Operated by Universities Research Association Inc ., under contract with the U .S . Department of Energy .
themselves everything they need to know and nothing more. A particularly important kind of object is the class, which represents types of things (e .g. the notion " valve"). An important relationship among classes is the notion of "superclass" which forms a hierarchy of related classes . Information and behaviors are inherited through this hierarchy from class to subclass . This is often useful in control systems . For example, "Kautzky valves" might be just like regular valves with a few exceptions. The object-oriented approach provides a standard way to code the relationship and the differences with no duplication of code . In designing the OOC protocol and the code which implements it, some goals were : (1) to make easy things easy to do ; (2) to make complicated things possible to do ; (3) to do common things in standard ways; (4) to allow unusual things to be done with minimal
constraints ; and (5) to maximize separation of concepts . OOC achieves the first four of these by being extensible, - s allows the last by being modular wits a fine grain . multiple use of code . For example, the notion of doing something periodic illy is represented by a certain kind of object that can lo anything periodically .
OOC is built on an independent, lower-level base of functions supporting tagged data called molecules . The functions of this layer support creating and destroying, reading and writing, manipulating and evaluating molecules .
0168-9002/90/$03 .50 © 1990 - Elsevier Science Publishers B.V . (North-Holland)
XI . SOFTWARE METHODS
34 8
LJ. Chapman / Object-oriented communication protocol
2.1 . Molecules
Each molecule comprises a tag together with data whose size and format depend on the tag. In addition to simple tags such as INTEGER and STRING, there are more complicated tags like MESSAGE. A molecule resides in a small fixed-size block of memory called a "place" . There are several kinds of molecules : (1) simple vs extended, (2) rigid vs elastic, (3) atomic vs multiple, (4) special vs ordinary. Simple molecules are those whose data fit in a place ; extended molecules use the data field as a pointer to another block. Rigid molecules are those whose data is always the same size (e.g. 8-byte reals always have 8 bytes of data); elastic molecules have varying sizes of data. Multiple molecules contain submolecules; atomic molecules (e.g. integers) do not . The basic multiple molecule has "#" as its tag and is called a "multimolecule." Multimolecules can contain any number of submolecules ; they are, therefore, elastic. Special molecules have restrictions on their submolecules. For example, a MESSAGE molecule (extended, rigid, multiple, special) contains two submolecules: one for the message type and one for the parameter. The parameter can be anything from a simple Boolean to an arbitrarily complex combination of submolecules of any type. As another example, a very generic PID-loop object can be written which accepts any kind of numeric input. The use of tagged data simplifies the higher layers and makes them more L.owerful. 2.2. Molecule evaluation Any molecule can be evaluated . Simple molecules like integers simply evaluate to themselves. STRING molecules are looked up is the dictionary object which maps STRING molecules to any kind of molecule . SEND molecules are evaluated by sending a message to an object, receiving the REPLY, and using the result as the value of the SEND. Multimolecules are evaluated by evaluating all of their submolecules recursively . A "#" of SENDs, for example, sends several messages and evaluates to a "#" of REPLIES to those messages. beet in T..++vim TCP, thsm ;vo -alnot;- --t ~., .,..e -.-- ac .-.-+~ ~aav rar»re aw .xavx .v v ..aaasu.avaa a1iY0~ OlneV times be turned off. For this purpose OOC includes quote ('), backquote (`) and comma (,) molecules modeled after those in LISP. 2.3. Terminal I/ O
Any molecule can be represented as an ASCII string. OOC provides terminal objects which run LISP-like evaluation loops. The user types a molecule, it is
evaluated and the value is printed . Polish prefix notation is used. The tag (e.g. integer2, for two-byte integers) appears first and is followed by whatever data are necessary (based on the tag) to complete the molecule. (For convenience, the tag is optional for certain common molecules such as four-byte integers.) The following example shows a multimolecule containing three submolecules, one of which is itself a multimolecule containing two Boolean sub-submolecules . Every molecule is underlined : Enter molecule: # 3 1000 real 4 #2 T F Evaluated as:
#3
1000 4.000000e + 00 #2 T F
3. Objects Every object contains instance variables and a pointer to its class, another object which represents what kind of thing it is. The class relationship can be read "X is a Y". For example, "this particular object (called VI) is a VALVE". An object's class determines the structure of its instance variables . Classes are themselves objects . Their class is a special object called "CLASSES" . For example, " VAL"ES is a Cf,ASS" . One of a class's instance variables is a pointer to its superclass. (OOC supports only single inheritance .) The superclass relationship can be read "every X is a Y". For example, "every KAUTZKYVALVE is a VALVE". Continuing up the inheritance hierarchy, "every VALVE is an OBJECT" . OBJECTS is another special-class object. It is at the top of the hierarchy, and is the only class which has no superclass. The other important instance variable for a class is the mapping from message types to methods. Methods are C functions which are executed when messages of a particular message type are received . For example, when a VALVE object receives a READ message, the C function MethodRead within the C module Valves is executed. An object can respond to the message types in its class, its superclass, and so on up the hierarchy . Also, the method in one class can be a sandwich around the same message type's method in its superciasses. A method may also send any message to any object, including the object executing the method itself . This formulation of the object-oriented methodology (nu invented by TTte), with two special objects (OBJECTS and CLASSES) is a beautiful and powerful
L.J. Chapman / Object-oriented communication protocol
concept, with OBJECTS and CLASSES forming an elegant yin/yang pair: CLASSES is a CLASS. OBJECTS is a CLASS. Every CLASS is an OBJECT. 3.1 . Sending messages
Objects may send each other messages by calling C functions . An operator may send messages to objects by typing a SEND molecule . In this example, "Age" is an object which knows homer long ago the system started running, and returns that number of milliseconds in a DURATION molecule with an eight-byte hex ($) value : Enter molecule:
send Age Read-,
Evaluated as:
duration $0000000004A459F2.
3.2. Addressing Objects are addressed using "object descriptors ." The simplest object descriptor is an OBJECT molecule containing a pointer to the object in memory. This is most often used by other objects in the same processor. Objects in other processors typically use an "OID" molecule which contains a four-byte object identifier. These are chosen by the application designer and must be unique within a processor but need not be globally unique. OOC evaluates OIDs by looking up the value in the object-group object which maps OIDs to other object descriptors, typically to OBJECTs . Distant objects can be addressed using global object descriptors containing network identifiers, node numbers, task identifiers and remote object identifiers . In the spirit of imposing minimal constraints, OOC strives to allow as much flexibility in addressing as is reasonably easy to implement. 3.3. The dictionary object OOC provides a standard dictionary object which maps STRING molecules to any molecules. In particular, objects can be given names which map to object descriptors. Any object (e.g. a human at a terminal) can add information to the dictionary object by sending it an "Add Entry" message. The dictionary can then be interrogated with "Read Definition" and "Read Key" messages. Terminal objects use the dictionary to help evaluate what the user types. If the input string contains any tokens not directly interpretable as molecules, the terminal converts them to STRING molecules. STRING molecules are looked up in the dictionary and, if found,
349
evaluate to whatever value the dictionary has for them; otherwise they evaluate to themselves. Users can take advantage of this. For example, if a complicated message is to be sent repeatedly, the user can name it, add it to the dictionary and henceforth simply type the name rather than the entire message. 3.4. Dynamic creation of objects
To create objects, one sends a "Create" message to the proposed object's class. The result is an object : the new instance of the class. 3.5. Volitional objects
Classical objects are passive in that they only act upon receipt of messages. Control systems also require objects that can act on their own volition. OOC provides the class of volitional objects. Each subclass of volitionals defines a task that is executed within each object of that subclass. For example, a PID loop might be implemented as a volitional object with a periodic task which sends "Read" messages to its input object and "Set" messages to its output object. 4. Combining concepts The OOC object layer is built upon the molecule layer. Molecules represent the objects themselves, messages a.nd replies from one object to another, and parameters and results within those messages and replies. The instance variables within an object may be molecules but are not required to be, in order to maximize freedom for application programmers designing object classes. A special message type, "Eval", allows any object to request any other object to evaluate any molecule. (The method for doing this is inherited from the top of the class hierarchy, so all objects can do this.) An interesting combination of molecules and objects is the class of "evaluators" . These are objects which remember a molecule (as an instance variable) and evaluate it on demand, remembering the value molecule (as another instance variable). If the molecule to be evaluated is complex, a collection of "Send" molecules r__ " U-*,,mccoeta to an eval 9ltÇLT causes `d LUl li1JtLL1SbG, tta1aa vâav aaavu~s+~.o . number of submessages to be sent and their results combined . An even rnore powerful class, a subclass of the volitional objects, are the "periodic evaluators" which are like evaluators except they evaluate their molecule periodically . Fig . 1 illustrates a periodic evaluator (pl) with a very complicated molecule, a SErTD molecule containing SEND molecules. Here we have an object that periodically sends a number of messages to various XI . SOFTWARE METHODS
350
L.J. Chapman / Object-oriented communication protocol
O ® o
Key
Object Instance Variable Method Task
X-6Y Pointer
X-}Y Message (X sends to Y) X< Y Creates (X creates Y)
Fig. 1 . Creation of an object which periodically reads some temperatures and sends the values to a window object which displays them graphically. objects, combines the results and forwards the composite result to a window object (winl) . Fig . 1 also shows how a terminal object (terml) creates the periodic evaluator object (pl) by sending a Create message to the periodic evaluators class (Peevs). The terminal names the newly created periodic evaluator by sending an Add message to the Dictionary object. What the user types is shown below after "Enter molecule" followed by what messages are sent (see numbered arrows) . Enter molecule : send Dig Add # 2 pl send Peevs Create (1) User at terminal asks Peevs class to create a new periodic evaluator object . (2) After creating new object, Peevs sends it IsNew .11 :__ 9a.essage, s. teUulg it to initializ initializee . Peevs returns address of object to user. (3) User names the new obiect "pl" by sending an Add message to the dictionary. The value of "pl" is the address returned by Peevs . Enter-molecule: send pl Set 'send winl Know ` val temps #3
send t1 read send t2 read send t3 read (4) User tells pi to read all three temperatures and send the values to the window. Enter molecule : send pl SetPeriod 1 (5) User tells pl to do it once per second . (6) Pl's task triggers pl once per second. Each time, pl sends Read messages to temper(7-9) ature objects . (10) Pl sends the values to the window for it to display . ((6)-(10) Repeat) 5.
isc
ion
ihe notion of tagged data has given OOC great flexibility . The notion of molecule evaluation has proved very powerful . Both of these notions exist in LISP, and it bothers me still that OOC reproduces some of LISP's basic functions. I did not use LISP itself for fear that OOC would become too large and inefficient, but this inay have been a mistake because as OOC has grown it has needed more and more LISP functionality.
L.J. Chapman / Object-oriented communication protocol
Two ideas popular in the field of artificial intelligence (AI) have been important in OOC's development. The first is that experimental code is a good thing. I could not have completely designed and then implemented OOC on the first try. The process of implementation is itself illuminating and leads to design changes. OOC has evolved considerably since its inception. New ideas have been added, and some old ones have lost the competition and died . Others have survived, living side by side with and sometimes overlapping their fellows. This may sound messy or inelegant. Actually it is a good thing. That is the second idea from AI : the utility of multiple paradigms. Certainly one can force all pro-
35 1
gramming into any one paradigm. The fundamental axiom of computer science states that any algorithm can be coded in any language. But AI has shown that no one paradigm covers all problems in a natural way. Rather than force one's problem into whatever paradigm is available, it is far more efficient (in development time) to be able to choose the paradigm most appropriate. In particular, OOC's two basic concepts, molecule evaluation and message seeding, overlap, but each is more natural for certain needs. OOC is most powerful when the two interact . Lists are a good example (a periodic evaluator evaluating a complicated molecule).
XI . SOFTWARE METHODS