(To appear in OOPSLA'95)

Object-Oriented State Machines: Subclassing, Composition, Delegation, and Genericity

Aamod Sane ¡ and Roy Campbell University of Illinois at Urbana-Champaign Department of Computer Science

1304 W. Spring®eld Avenue, Urbana, IL 61801 £ email: ¢ sane,roy @cs.uiuc.edu www: http://choices.cs.uiuc.edu/sane/home.html

¤¦¥¨§ ©  © machines by incrementally modifying and combin- ing other independently designed machines. In ad- Software speci®cation and implementation techniques dition, we present a novel, highly ef®cient technique based on state machines simplify design, coding, and validation. However, large systems require complex for implementing state machines that extends object- state machines. Incremental construction techniques oriented approaches such as the rei®cation technique can control this complexity. In this paper, we present a (RT) [13, 8]. Our technique facilitates incremental construction technique that permits derivation of com- derivation of state machines using subclassing, com- plex state machines from simpler state machines. The position, delegation, and genericity (henceforth called technique uses subclassing, composition, delegation, object-oriented-techniques (OOT)),and improves upon and genericity to incrementally modify and combine simpler machines. the reuse afforded by RT. In addition, we present a novel implementation technique that uses exactly one table-lookup and one We motivate the use of subclassing by consider- addition to dispatch events on derived state machines, ing a simple virtual memory (VM) paging scheme no matter the depth of the derivation. As an example, (Figure 1) that is enhanced to support copy-on-write we describe the derivation of a complicated distributed virtual memory scheme from a simple paging virtual (COW) [1] (Figure 2). In Figure 1, a virtual memory memory scheme. page may be mapped into physical memory so that it is

accessible. The page may be unmapped to store it on

   © ©  backing store and release physical memory for other use1. The state machine in Figure 2 supports copy- Many designers advocate the use of state machines on-write. COW allows data created by one process to to specify and implement software systems. For ex- be shared with a different process without requiring ample, reactive system designs [10] and object-orien- the data to be copied. Instead, the physical pages on ted analysis and design [26, 2, 5] use state machines. which the data resides are shared between processes However, large systems require complex state ma- until the processes modify them. Data is ªcopiedº chines. In this paper, we introduce object-oriented by mapping the associated physical page into the vir- techniques that permit the design of complex state tual address space of the target process with read-only

access. However, upon a write access, the ªcopiedº Supported by CNRI contract CNRI GIGABIT/UILL. data is duplicated by copying the page to a new phys- ical page and changing the read-only access to write access. The two ®gures show several similarities, for example states RMapped, WMapped, are simi- 1For simplicity, the state machine diagrams do not show loops (transitions that do not change state).

!F"%$>&(G)H+-,I.

1 3 1 3

0 0 2 2

!#"%$'& (*)'+-,/.

JK4L56678 JM9N:

!#"$>&%PQ&R"ST !#"$>&UWVEX+& ,I.

01 32 10 23

4¦5667%8 9;:<=5667%8

YZ"R[\& ];^_!\`#,/. !F"%$>&UWV-X+a& ,/. Yb" [c& ];^R!c`#,I.

!#"$>&@?BA%AC&@DED ,/.

!F"%$>&(G)H+-,I.

01 23 10 23

de4¦5667%8 d9;:<=5667%8

Figure 1: Page States in a !F"%$>&Pf&R"Sg,I. Simple Virtual Memory System Figure 2: Page States for Copy-On-Write

lar to Mapped and methods pageRead(), pageWrite() can be eliminated if necessary. Section 6 summarizes are similar to pageAccess(). The two ®gures have topics such as subtyping and nested states that are not differences corresponding to the additional behavior, discussed in detail due to space restrictions. We con- for example, makeCopy() is added and pageWrite() sider related work in Section 7, and in the conclusion causes transitions from RMapped to WMapped. (Section 8) we indicate possible generalizations of our Using the techniques in this paper, the similari- techniques and other avenues for further research.

ties between the two state machines can be captured

h i gm by subclassing. VM machine code corresponding to F¥jckl g§R§  similar transitions can be reused in the COW machine, and new COW code need be written only for additional In this section, we consider how to derive the COW behavior. The paper presents other examples showing machine (Figure 2) as a subclass of the Simple VM how complex state machines that support distributed machine (Figure 1). We ®rst show that standard tech- virtual memory (DVM) are also easily derived using niques such as RT [13, 8] block certain kinds of reuse. OOT, while maximizing reuse. Then we observe that this is not an artifact of any particular implementation technique. Reusing code Besides maximizing reuse,our techniques also show while subclassing state machines is dif®cult because that in order to properly de®ne subclassing, compo- the IS-A relationship between states of base and de- sition, etc., for state machines, we have to reconsider rived machines, and the BECOMES-A relationship the usual notion of Self (ªthisº in C++). Section 2 induced by state transitions, interact with each other. considers this issue in greater detail. In the remainder Hence, a general solution requires a rede®nition of the of the paper2, we give examples of composition, del- notion of Self that accounts for both relationships.

egation, and genericity in Section 3. The de®nition of

 

§q nsr Self (Section 2) leads to formal de®nitions of OOT in nNog§Rop o'§ © I©%  Figure 3 shows an im- terms of embeddings (Section 4). Analysis based on plementation (in OMT-like notation [21]) of the VM embeddings suggests a fast implementation involving state machine (Figure 1) using RT3, where states are a single indexed table lookup (Section 5), regardless rei®ed as objects, and method calls implement state of the height of the subclassing, composition, or del- transitions. egation hierarchy. A space-ef®cient implementation In Figure 3, pages are instances of the class Page. of generics requires one more lookup, but the lookup PageState is the abstract class that declares the 2We use Mealy machines [11], but since actions may be asso- methods for each state of a page, while the classes ciated with either source or destination state objects, our technique 3We build on RT. For comparisons between RT and other also applies to Moore machines [11]. techniques see [8].

ƒR~yR~{

„j @†ˆ‡@‰Š‹ \Š‡

tu@v w

x\yRz{ |}~%€ Œ¨@Ž'  ‘’¨“”

x\yRz{R‚ ‚ { ƒ ƒH%€ Œ¨@Ž' •– –  — —j“”

šfu_› ›%w@œ jž Ÿ uR›R›%w@œ

ƒR~yR~{ ˜ ™x\yRz { |} ~C€

ƒR~yR~{ ˜ ™x\yRz {R‚R‚ { ƒ ƒ¨@€

x\yRz{ |}~%€ x\yRz{ |}~%€

x\yRz{R‚ ‚ { ƒ ƒ¨@€ x\yRz{R‚ ‚ { ƒ ƒ¨@€

Legend: inheritance, instance variables, method implementation.

Figure 3: Reifying States as Objects

Mapped and Unmapped represent the concrete sta- ce(). Thus, with RT, the code for Mapped::pageOut() tes of a page. Each page object maintains a current cannot be reused in both methods without modi®ca- state variable state, that points to an instance of tion. Mapped or Unmapped. Methods of class page (e.g., In abstract terms, the problem is that since pa- Page::pageOut()) invoke the corresponding method of geOut() is implemented in the superclass, it cannot the PageState. For instance distinguish between the states WMapped and RMa-

Page::pageOut() pped. We observe that when state machines are de- £ ¢ state = state->pageOut(this); ; rived, one transition in the base state machine can The state methods de®ne actual behavior, as in correspond to a number of transitions in the derived Mapped::pageOut(Page * p) states. In general, a transition's source and destina-

¢ p->flushMMU(); p->writeToDisk(); tion state arities may change in unrelated ways during

return Unmapped::Instance(); £ ; subclassing. Therefore, we need two different ways to The state objects themselves have no instance vari- map the source and destination states of a transition. ables, so there is only one systemwide instance of each In the following, we present an implementation based concretestate. The method call Unmapped::Instance() on this observation.

returns a pointer to the system-wide instance.

i  gmMi

¨§  ©% g©oe¢q F£g§ Using RT, the COW machine might be imple- #k/g©%¡ Instead of returning a mented directly in a similar manner. However, sup- programmed constant, we return the next state indi- pose that we want to reuse VM machine code for meth- rectly by looking-up the actual state we want to return ods such as Mapped::pageOut(), since the behavior in tables called StateMaps. Derived machines are then is similar to that of WMapped::pageOut() and RMa- constructed by systematic modi®cation of StateMaps, pped::pageOut(). We might derive a class WMapped and base state methods are inherited without change. from the class Mapped, hoping to reuse Mapped::pa- A StateMap is similar to a C++ VTable [7]: C++ geOut(). But now there is a problem: where Map- virtual functions are dispatched using the VTable, so ped::pageOut() returns Unmapped::Instance(), WMa- that derived classes can replace ªvirtual functionsº of pped::pageOut() must return WUnmapped::Instance(). the base class with their own versions. Similarly, a Although behavior in the two states is similar, the StateMap is used to determine the actual next state, state transitions differ for the COW machine. If we so that a derived state class may ªreplaceº it with the attempt to reuse Mapped::pageOut() by rede®ning Un- next state appropriate for the derived machine. Fur- mapped::Instance() to return WUnmapped::Instance(), thermore, just as every C++ class has its own VTables, we ®nd that RMapped::pageOut() cannot reuse Map- every state has its own StateMap. ped::pageOut(), as it must return RUnmapped::Instan-

¬ ­  m   

¥L¯*o¨k°o ¨©%  ¥± ³²Qo o I¡©@´ Using StateMaps (Figure 4), we write: §®£§R ©%¡ Mapped::pageOut(Page * p)

¢ p->flushMMU(); p->writeToDisk();

¬µ‹ ­  §«£§ ¡©% 

return map->Unmapped(); £ ; where map is an instance of StateMap. Method State machines are composed to combine behaviors map->Unmapped() invokes Unmapped::Instance(), de®ned in component machines. We demonstrate returning the pointer to the system-wide instance of composition by constructing a distributed virtual mem- Unmapped. ory (DVM) protocol machine (Figure 8) out of a virtual Figure 5 shows how the COW machine states are memory machine (Figure 6) and a networking ma- now derived from VM machine states. Class WMa- chine (Figure 7). DVM [24] provides the illusion of pped is derived from class Mapped, but instances a global shared address space over networks of work- of WMapped are initialized to have pointers to an stations, whose local memories are used as ªcachesº instance of class StateMapW, which is itself de- of the global address space. The caches have to be rived from StateMap. Now if pageOut() is actu- kept consistent: a simple approach allows only one ally invoked from an instance of WMapped, page- machine to access a shared page at a time. If an- Out() will invoke map->Unmapped(). Since in other machine attempts to access that page, its virtual WMapped, ªmapº is an instance of StateMapW, memory hardware intercepts the access, and its fault map->Unmapped() returns WUnmapped::Instan- handler fetches the page from the current page-owner. ce() as required. Similarly, RMapped may indepen- Thus, behavior for DVM has VM and networking as- dently rede®ne map->Unmapped() using pects. We de®ne VM and networking behavior using StateMapR. separate state machines, and compose them to get a

DVM machine.

i   gm

ogk ¤%¥G¦sog§¨o'§ ©%¤¦¥ § ©%¤¦¥ Kª§«¥og#j § In us- DVM-VM MACHINE: In a DVM system, pages may ual object-oriented programming, the Self (ªthisº) of be either DMapped, DUnmapped or Remote an object may be regarded as a function that binds (Figure 6). The DMapped and DUnmapped sta- method invocations at run-time. We have seen that tes are inherited from the simple VM machine (Fig- for state machines, we need two functions, one for ure 1). State Remote represents a page on some the source and other for the destination state. This remote machine, and remAccess() de®nes actions is because upon subclassing state machines, the IS- for pages accessed by a remote machine. The tran- A relation de®ned by inheritance between state ob- sitions are de®ned as though no networking were jects, and the BECOMES-A relation de®ned by state necessary. (The special state Null ignores all VM transitions interact. For instance, in Figure 5, the actions; it is used in composition. We always create relation ªa WMapped page IS-A Mapped pageº is Null and Error states for every state machine). programmed using ordinary inheritance between the immutable state objects, while the relation ªa Map- DVM-NET MACHINE: The networking machine (Fig- ped page BECOMES-A Unmapped page upon page- ure 7) implements a trivial protocol that sends a Out()º is incrementally modi®ed to ªWMapped page page to a remote machine, or gets one from a re- BECOMES-A WUnmapped page upon pageOut()º mote machine. It handles details like fragmentation using StateMaps. Thus, for state machines, Self is a and sequence numbering. pair of functions that de®ne how a transition in the DVM MACHINE: In the composite DVM Machine (Fig- base machine is mapped into a transition in a derived ure 8), suf®x Q indicates that in the composite state, machine. We say that the base machine is embedded the DVM-Net state is Quiescent, and suf®x N in- into a derived machine. Formal de®nitions based on dicates that the VM state is Null. We implement this idea are presented in Section 4. But ®rst, we transitions to and from RemoteQ using the net- see some examples of composition, delegation, and working machine. MappedQ and UnmappedQ genericity. inherit behavior from the DVM-VM machine.

¾

yx

ƒR~yR~{

„ @†‡@‰ˆŠ‹ \Š‡

tu@v w ¶ ·au¸·¹w šfuR›

º

x\yRz{ |}~@€ Œ¨@Ž'  ‘’¨“” yx x\{R»%€

¼ ½ ¾

x\yRz{R‚ ‚ {Rƒ ƒ¨@€ Œ¨@Ž' •– –  —R—F“a” yx x\{R»%€

šfu_› ›%w@œ žRŸ uR›R›%w@œ

º ½ ½

ƒR~yR~{ ˜ ™xyRz{R|}~g%€ yx x\{R»#¿ ¿EÀ ƒR~ y ‚ {¨@€

¼ ½ ¾ ½ ½

ƒR~yR~{ ˜ ™xyRz{‚ ‚ { ƒRƒ¨%€ yx x\{R»#¿ ¿ÁÀ ƒR~y ‚R{¨%€

x\yRz{ |}~%€ x\yRz{ |}~%€

x\yRz{R‚ ‚ { ƒRƒ¨C€ x\yRz{R‚ ‚ { ƒ ƒ¨@€

¾ ¼ ½ ¾ ¾ ¼ ½ ¾

yx\˜ ™ yxRx\{R»g%€ yx\˜ ™ yx x\{R»¨%€

¾ º ¾ º

yx\˜ ™ yx x\{»%€ yx\˜ ™ yx x\{%»%€

Figure 4: VM Machine Using StateMaps

¾

yx

„ @†ˆ‡¸‰ˆŠ‹ \Š‡

¶ ·u@·¹w šfuR›

º

Œ¨@Ž'  ‘’¨“” yx x\{R»%€

¼ ½ ¾

Œ¨@Ž' •– –  — —F“” yx x\{R»@€

šfuR›R›%w@œ žRŸ uR›R›%w@œ

º ½ ½

yx x\{R»#¿ ¿À ƒ~y ‚ {H%€

¼ ½ ¾ ½ ½

yx x\{R»ˆ¿ ¿EÀ ƒ%~y ‚ {¨@€

x\yRz{ |}~%€ x\yRz{ |}~%€

x\yRz{R‚ ‚ { ƒ ƒ¨%€ x\yRz{R‚ ‚ { ƒRƒ¨%€

Â#Ã*Ä

‰ˆŠ‹ \Š‡

¶ ·au¸·¹w šfuR›@Ê ¶ ·au¸·¹w šfuR› Î

º º

Œ¨@Ž'  ‘’¨“” yx x\{R»%€ yx x\{R»%€

¼ ½ ¾ ¼ ½ ¾

Œ¨@Ž'%Åc  ÆF“” yx x\{R»%€ yx x\{R»%€

Ë º Ë º

Œ¨@Ž'Ç%ÈcÉ ’R“” yx x\{R»%€'Ìf{R~‚Í yx x\{R»%€'Ìf{R~‚Í

ÊZšfuR›R›%w@œ Îgjž Ÿ u_› ›%w@œ

Ë º ½ ½ Õ º ½ ½

yx x\{R»#¿ ¿EÀ ƒR~_y ‚R{¨C€ yx x\{R»#¿ ¿EÀ ƒR~_y ‚R{¨%€

ËR¼ ½ ¾ ½ ½ ÕR¼ ½ ¾ ½ ½

Ó Ó

¾ Ë

yx x\{R»#¿ ¿ÁÀ ƒR~y ‚ {¨%€ yx x\{R»#¿ ¿ÁÀ ƒR~y ‚ {'%€

Ï Ï {R~RÐ\ÑR»ƒ x\yRz{ Ò ~{¨C€ ƒ

Ë º ½ ½ Ë º ½ ½

Ó

½

yx x\{R»#¿ ¿EÀ ƒR~_y ‚R{¨C€'ÌQ{R~‚Í yx x\{R»#¿ ¿EÀ ƒR~_y ‚R{¨%€\ÌQ{R~‚Í

{R»#ÌfÑR~RÐ\{ Ò ƒ y Ò { Ò {R»{RÔ

Ó Ó Ó Ó

½ ½

Ð\{ Ò ~{R» Ð\{ Ò ~{R» y Ò {

Class Page (see Figure 4), state classes WUnmapped and RMapped, and makeCopy() were omitted for brevity. pageRead() and pageWrite() inherit behavior from pageAccess(), but for RMapped and RUnmapped, pageWrite() also makes physical copies and changes protection. makeCopy() has to be de®ned for WMapped and WUnmapped. Otherwise, no new code is necessary.

Figure 5: Subclassing VM machine for COW using StateMaps

!#"$>& (*)'+E,I.

ØÙ ÛÚ

1 3 1 3

0 0 2 2

á7@Ý-âRã

Ö±4L56678 Ö±9N:

$>& +äN"%$>&,I. åg&@V@&%äN"%$>&,I.

!#"%$'&@?OA%A@&@D-DR,I.

Ú Ø

Ù Û

æ

ß ç°7@èCâ7R: Ý

!#"%$'&@?OA%A@&@D-DR,I. V@&@Y×?BA%AC&@DED ,/.

åg&@V@&%äN"%$>&,I. "A[>äN"$>& ,/.

ØÙ ÚÛ

é

7_:_8

Ø Ù ÛÚ ÙØ ÚÛ

d7R<*ÜÝ-7 Þ;ßà°à

Figure 7: DVM-NET State Machine

Figure 6: DVM-VM State Machine

!#"$>& (*)'+E,I.

1 3 1 3

0 2 0 2

æ æ

4¦5667%8 9N:

!F"%$>&¸?OA%AC&¸D-D ,/.

å¨&@VC&%äN"$>& ,/. V@&@Y×?BA%AC&@DED ,I.

Ú Ø Ú Ø

Ù Û Ù Û

é

á7@Ý-âRã\Þ 7R:_8HÞ

!#"%$'&@?OAAC&@D-DR,I. "A['ä;"$>& ,/.

Ø Ú

Ù Û

æ d7R

Figure 8: DVM Composite State Machine

1 3

Ø 0 2 ØÙ ÛÚ Ú

Ù Û

é æ æ

7R: 8'Þ 4¦5667%8 d7R<*ÜÝ-7 "A['äN"%$'& ,I.

DVM Machine: VC&@YW?OA%AC&¸D-D ,/.

1 3

2 0 ØÙ ÚÛ

Ö±4¦5667%8 d7R<*ÜÝ-7

DVM±VM Machine: VC&@YW?OA%AC&¸D-D ,/.

Ø Ø Ø Ú Ù ÚÛ Ú

Ù Û Ù Û

æ é æ

ß_ç°7@è@â%7R:RÝ 7R: 8 ß ç°7@èCâ7R: Ý "A['äN"%$'& ,I. DVM±NET Machine: åg&@V@&%äN"%$>&,I.

Figure 9: Example of Composition Methods of the composite machine reuse behavior ized by states (and possibly other parameters). Such a

de®nedê in methods of component machines by initial- template is instantiated binding parameters at compile izing StateMaps so that the states returned from com- time. Templates themselves can be subclassed and ponent methods are actually composite states. For composed; conversely, subclassed machines may be instance, Figure 9 shows how the composite method used to instantiate the same template. Thus, generic- MappedQ::remAccess() combines and reuses DMa- ity can lead to interesting patterns of reuse. For pped::remAccess() and Quiescent::herePage(). In the example, consider a DVM machine that allows mul- DVM-NET machine, Quiescent::herePage() returns tiple copies of read-only pages. Such a DVM-COPY the NET state Send, but when invoked from the machine is itself composed from a DVM-VM-COPY composite state MappedQ, it returns the compos- machine, and a DVM-NET-MULTICAST machine. ite state SendN. In turn, ackPage() when invoked These new components can be themselves derived from SendN, returns RemoteQ instead of Quies- from the DVM-VM and DVM-NET machines respec- cent. RemoteQ later gets used as a VM state. tively, and are also composed in similar ways.

We take advantage of this by de®ning templates

¬µIh m  g©  ¯*ogklo for DVM-VM (Figure 6) and DVM-NET (Figure 7) machines, and composing the templates to create a Delegation can be programmed using state machines template for the DVM machine (Figure 8). Now we [13], and in turn state machines may delegate be- can subclass this template to de®ne the composition of havior to other machines. For instance, Figure 3 more complex components. It is then instantiated with might be considered a description of how instances state machines for DVM-VM-COPY and DVM-NET- of Page delegate their behavior to the ªpage classesº MULTICAST. Figure 11 shows such a construction. MappedPage and UnmappedPage (see also [20]). Section 5 describes implementation techniques for The class of a Page object changes when it changes all the constructions above. However, in order to states, effectively changing the delegatee. Similarly, understand the implementation, we need precise de®- state machines may ªdelegateº their behavior to other nitions of our four constructions.

state machines, and the delegatees can be changed

¨m ªì§®¥ogF at run-time, much as individual states are changed in ë ordinary state machines. Sections 2 and 3 give examples in which machines As an example, consider the COW machine (Fig- are derived by simply modifying StateMaps. In this ure 2). When a page has no copies (states WMapped section, we make the notion of modi®cation precise and WUnmapped), the COW machine behaves like using embeddings to de®ne the four OOT's. a vanilla VM machine (Figure 1). However, when a page is copy-on-write, the COW machine behaves In Section 2, we observed that state machine code like a restricted version of the VM machine that al- can be inherited if the current state, the next state and lows only pageRead() Ð call this the RVM machine. the action method are bound dynamically. Therefore, With this viewpoint, a COW machine may be regarded we de®ne subclassing, composition, etc., in terms of as a two-state machine, with states CMapped and mappings between triples of source state, event, des- CUnmapped, that delegates its events to the state tination state. Such triples are called transitions, and machines VM and RVM (Figure 10). The methods mappings between transitions are called embeddings. pageWrite() and makeCopy() changes the delegatees, More formally, using the standard [11] de®nition changing the behavior of every state at the same time.

of state machines, de®ne two state machines í (base)

µI 

²fo oj I ©@´

We say that a state machine is a template if it de- clares states and events, and its actions are parametr-

!#"%$'&UWV-X+a&,I.

î ð î ð

!#"$>& (*)'+E,I. !#"$>& (*)'+E,I.

01 23 01 23 01 23 01 23

de4¦5667%8 d9;:<=5667%8 JK4L5667%8 JK9;:<=56678

ï ñ ï ñ

!#"%$'&%Pf&R"Sg,I. !#"%$'&%Pf&_"STUWV-X+a& ,/.

YZ"R[\& ];^_!\`#,/.

ð î

!F"%$>&(G)H+-,I.

1 23 01 23 0

ò ò

4L5667%8 9N:

ï ñ !#"%$'&@?OAAC&@D-DR,I.

Figure 10: COW Delegates to RVM and VM

ØÙ ÚÛ ØÙ ÚÛ

Ö#óQ4*ôóf4õ4¦5 âRã_ç¡: 7 ÖFóf4*ô%Þ öc÷ø4¦5 âRã_ç¡: 7

Ù Û

Ø Ú

ÖFóf4ù4L5 â_ã_ç¡:_7

Ú Ø Ú Ø

Ù Û Ù Û

òjúBûHü òÿ é

Ö#óf4=ôóQ4*ô 4L5 âRã ç¡:_7 Ö#óf4=ô¸Þsöc÷ô%4×9sý-÷Qþ ÷ 4L5 â_ã_ç¡:_7

ØÙ ÚÛ

ò#úOûHü

ÖFóf4*ô 4L5 âRã ç¡:_7

Legend: inheritance, instantiation

Figure 11: Using Genericity, Inheritance, and Composition

¡

í 6 87 and (derived): 1. A transition 6 of the state machine (

¤§©-  ) may be mapped to one or more tran-

¡

í ¢¤£¦¥¨§©¥¨    ¥   §  

6 6 79¤§©

+ +

sition + of the state machine ( ).

§  ! "#£¦¥¨§©¥¨  %$& ¥  %$'£(¥¨§©¥¨   *)

¡ 6

2. For every transition + in the derived machine ,

¡

either there is exactly one transition 6 in the base

¢¤£¦¥¨§©¥¨ +,  ¥ + ¤§©- +

í 6 6

machine such that is mapped to + , or the

¤§©- "#£¦¥¨§©¥¨ $& ¥ $'£(¥¨§©¥¨  )

+ + + +

¡ 6 event for the transition + is new to . All state and event sets are disjoint. The ®rst condition allows many states in a derived A state machine has states, events and transitions. machine to inherit behavior from one state in the base

Transitions are triples such as ¢/.¦ 01¦"*)2,3% , where S is machine. The second condition ensures that every the source state, ev() the event, and D the destination machine in the derived state de®nes some behavior

state. An event need not have transitions to all possi- (possibly a null or error state) for every event de®ned

¤§©-  ¤§©

ble destinations, so and + are subsets of in the base machine. The second condition also im-

:; ¤§©- 

the cartesian product. But note that all combinations plies that no two transitions 6¤ and from

6 § + of source state and event must occur in the transition are mapped to the same transition + from , so relation. We do not distinguish between input events derived states do not have ambiguous behavior. and output actions. In object-oriented state machines, As an example, consider the VM (Figure 1) and

the name of a method is the input event, and its de®ni- COW (Figure 2) state machines from Section 2. The tion constitutes the output action. Methods of a state transition ¢ Unmapped, pageAccess(), Mapped from

object can be invoked either when it is the current the VM machine is mapped to ¢ WUnmapped, page-

state, the next state, or both, so both the Moore and Read(), WMapped and to Mealy machines are easily implemented. ¢ RUnmapped, pageRead(), RMapped , as well as

Embeddings are de®ned as mappings from one set the transitions for pageWrite(). The embedding from

¤§© ¤§©- of transitions to another, e.g., from to + . VM to COW satis®es all of the conditions, so the Embeddings need not be functions, since one transi- COW machine is a subclass of the VM machine. tion in a machine can be mapped to many transitions When a transition from a base machine is mapped in another machine. In the following, we de®ne sub- to a derived machine, in the scheme of Figure 5, for classing, composition, delegation and genericity using each transition the mapping is programmed as follows: embeddings.

< The class for the source state in the derived ma-

µ‹ i ¨m ­  m  

#¥#ck° ¨§ §R ¥ §«£ˆ§R ©  ¥±¯*ogklo g©  ¥F 

ë chine inherits from the class of the source state

 oj I ©@´ ²fo in the base machine. In our example, the classes WUnmapped and RUnmapped are both sub- The OO constructions are de®ned as embeddings that classes of Unmapped.

satisfy certain consistency conditions. Note that these < The destination state in the transition from the de®nitions do not guarantee subtyping (the de®nitions derived machine ªreplacesº the destination state specify the mechanism), since subtyping is a behav- of the base machine. This replacement is pro- ioral notion (subtyping speci®es the policy). Section 6 grammed by using different StateMaps, as we considers subtyping.

discussed in Section 2. The destination states

  i gm

54  ©%¡ ¨¤ F¥jckl g§R§  ¯*o need not be subclasses.

We say that a state ma- ¡ < An event (method) of the base machine is mapped chine is derived by subclassing í , if there is an

embedding (i.e., a mapping) from the set ¤§©-  , the using virtual functions or equivalent mechanism

in the language, or by programming an actual ¤§© + set of transitions of í , to the set , the set of transitions of ¡ , such that: call. Thus, in Figure 5, the pageOut() method is inherited in the COW states as a virtual function,

   

ªBA  o © §®£k°o§¨o ©% g©  however, the pageRead() and pageWrite() meth- @ ods actually invoke the pageAccess() method. We show how embeddings can be programmed so that This method works for many cases, however, in Sec- event dispatch requires only one addition and a single tion 5 we see it does not always suf®ce. table lookup. We ®rst show that the StateMap scheme

of Figure 5 cannot be used to program all embeddings.

  ­ 

¯*o54  ©%¡ ¨¤ §«£§ ¡©%  We say that a state We also discuss limitations due to non-determinism.

machine ¡ is derived by composing two (or more)

i

C*oHog ¤-F ©% ¨©%oe¢ #£ED j  F§¨o'©%o § =

machines í and if there is an embedding (i.e., a Suppose that ¤§© >

mapping) from the sets ¤§© and to the set ¢/.¦ 01,JK"#)#IHL

two transitions ¢/.¦ 01,FG"#)#IH and of a

¤§© ¤§©-  %? ¤§©- + + , such that both maps from

base machine í are embedded into two derived state

¡

¤§© >%? ¤§© and + individually satisfy the condi- machine transitions ¢M.N 01,FO"*)2HPN and

tions for subclassing, but we need to replace condition

¢/.N01QJK"*)2,RSNT

¡ respectively. Then, the destination 6

2: For every transition + in the derived machine , state in the derived machine depends on the event í

either there is a transition 6 in at least one of or invoked. So we need a different StateMap in Sd de-

= 6 6

such that is mapped to + , or the event for the ¡ pending on the event. Therefore, unlike Figure 5,

4 6 transition + is new to . events of a single state may require multiple State- Examples of transitions for composite machines are Maps that are parameters to action methods. Now, readily apparent in Figures 6, 7, and 8. Furthermore, only non-deterministic transitions pose a problem.

since each mapping is individually a subclass map-

 

* o'©o @§   §§ ping, maps between transitions may be programmed C State transitions are non-deter- in the same manner as for subclassing.

ministic if two transitions with the same source state

 m 

 and event have different destination states. Figure 12 ¯*o54  ©%¡ ¨¤Z¯*ogklo g© 

We say that a state ma- shows a networking machine that can receive mes- ¡

chine is derived by delegating to two (or more) sages transmitted as two fragments. The non-determi- =

machines í and if there is an embedding (i.e., a nacy is due to NoFrags::recv(), since the criterion used ¤§© >

mapping) from the sets ¤§© and to the set to choose between the destination states is hidden.

¤§©- ? ¤§©- +

¤§© + , such that both maps from Now suppose the Two-Fragment machine in Figure 12

¤§© >%? ¤§© and + individually satisfy the condi- is subclassed to create the Three-Fragment machine tions for subclassing. However, at any particular state in Figure 13. In Figure 13, NoFrags::recv() has more of the program, only one of the possible embeddings possible destinations Ð we say that the derived ma- of the components may be true. chine Three-Fragment increases non-determinacy. A

StateMap cannot be used to increase non-determinacy,

  

¯*o54  ©%¡ ¨¤q²fo o  ¡©C´

We say that a machine since one entry of an arraycan map to only one destina- ¡

is an instantiation of state machine template í if tion state; therefore, method NoFrags::recv() has to be

there is a one-one mapping between the states, events, rede®ned for the Three-Fragment machine, although

¡ í actions, and transitions of í and . is called a it may invoke the base-class methods to achieve some template because its actions are parametrized by states reuse. In the following, we assume that derivations (and possibly other objects). Otherwise, it is just like do not increase non-determinacy.

a state machine.

µ‹   

@ §®£k°o§¨o © g©%¡

Now that we have de®ned our constructions as maps between transitions, we investigate what sorts of maps In this section, we show that all embeddings apart can be implemented ef®ciently. from those that increase non-determinacy can be ef- ®ciently implemented. We statically precompute the 4 We assume that the notation used to describe state machines states to be returned, methods to be dispatched, etc. enforces unambiguous names for events and states as necessary. Then, instead of programming individual StateMaps

1 3

0 2

ácçWVIè-Ý%á,V¹5X

VC&RAIUc,/. V@&RAIUc,I.

01 23 01 23

ÞFÜgá,V¹5Xè ÷SYܨá,V/5Xè

1 3

0 2

é

7%â@ÜH:_8'á5V/5X

VC&RAIUc,/. V@&RAIUc,I.

Figure 12: Two-Fragment receiver

0 1 23

ácçWVIè-Ý%á,V¹5X

VC&RAIUc,/. V@&RAIUc,I.

0 0 1 23 1 32 01 23

é

ÞFÜgá,V¹5Xè ÷SYܨá,V/5Xè 7%â@ÜH:_8'á5V/5X

VC&RAIUc,/. V@&RAIUc,I.

0 1 23

÷±ã çWV/8Há,V¹5X

VC&RAIUc,/. V@&RAIUc,I.

Figure 13: Three-Fragment receiver

in C++ (Section 2) and using C++'s implicit VTables, from other states (Inner calls).

we construct our own composite VTables and State-

^ gma^ ­

`_c g©%oj ˆk¡k°§ Maps for all states together, considered as a single £¨©%¹§¨ Using the implementa- object. Then we have: tion of Figure 4, an Outer call to pageAccess() such as THEOREM 1 (EmbeddingsUsingArrays) Given an em-

bedding from a base to a derived machine, method Page::pageAccess() £ calls on derived states may be dispatched with one ¢ state = state->pageAccess(this); ; addition operation, followed by one table lookup, re- involves two dereferences, one for the state variable gardless of the height of the subclassing, composition, and another to look up pageAccess in the VTable of or delegation hierarchy. state. To optimize, we concatenate the VTables for all state objects of a machine in a composite CVTable. We use induction on the hierarchy of embeddings. In The current state is represent just by an integer. Now, our base case, we indicate how to achieve two step methods are dispatched simply by indexing into the dispatch in a state machine without any ancestors. CVTable using the current state and the method index, In the inductive step, we indicate how the tables of which involves only one addition and one lookup.

ancestors can be extended in a derivation so that no

gm #

additional lookup is required. ^ `_c o L ˆk¡k°§

£¨©%¹§¨ Dispatching an Inner call

µIh ­ i  

¦s g§Ro g§RoZ ‹§®£k°o ¢ ˆ[¨ o]\¦ © [¨g©¨¤ © @ to pageAccess() such as

oH§ ©%F § Unmapped::pageAccess(Page *p)

¢ p->getPhysicalPage(); p->readDisk();

We show how to optimize method calls and state return map->Mapped()->pageAccess(p); £ ; lookup for a single machine that has no ancestors.

in Figure 4 involves one lookup in a StateMap fol-

µIhµ¹ ^ gm

£g©%‹§ W_\ ¢ o'© [¨e ¯= §£g ¨© [ @ lowed by a VTable lookup. To optimize, we maintain separate inner call vtables (called IVTables) that have Method calls on states may originate from the object precomputed pointers to methods actually invoked in that uses the state machine (Outer calls), as well as Inner calls. Thus we need only one table lookup. The particular IVTable depends on the event dispatched Thus, we have shown that state machines can be in-

(i.e., method invoked). herited with fast dispatch.

µIhµ h ^ gm i

@ £g©%‹§ W_\ ©% g©ocbc#¦d¨#£

­  §®£§R ©%¡ Composition is de®ned (Section 4) as a set of embeddings each of which de®nes a subclass, The StateMap to be used for a transition is determined so we apply the above technique for each component during the Outer call, along with the IVTable. Thus, and the composite.

the next state in an embedding can be returned with

m  ¨©%  only one table lookup. This completes the description ¯*o¨k°o of the base case. Delegation is also de®ned as a set of

embeddings each de®ning a subclass. So for each

µI¬  i  

re[go ©`f'o ©%oj£(Z³¢q [g o'§hg  © [ø¤ © @ delegatee, we construct tables as above, and switch

oH§ ©%F § tables if the delegatee changes.



²fo o   ©@´

For the inductive step, consider two machines í and All instantiations of a template can share

¡ ¡ í , such that is derived from í . itself is presum- the structure of the template. Since instantiations only ably derived from other machines; we assume that differ in the parameters, we simply use method ªpoint-

events of í are dispatched as for the base case. We ersº from the CVTable and IVTable as indices into ¡

show how to construct tables for , such that every Instantiation Tables. Every instantiation uses a dis-

iS í i table in has a corresponding table + that extends tinct instantiation table. Instantiation tables can also iS . Thus, all indexing operations from the source be eliminated by making copies, so, any particular code for í work without change, and have no extra generic machine can be sped up if necessary (see Sec-

overhead. tion 3.3).

i gm

F¥jckl g§R§ 

µ i ^

@ ë £g o f'o ¤[go' 

As an example, let í be the VM ma- chine from Figure 1, and ¡ be the COW machine from Figure 2. The following arguments hold for these two In the standard non-object-oriented table based imple- machines. We have three cases: mentation of deterministic state machines, we need

¡ one table that has the next state for every combina- CVTABLE Since every state of machine responds

¡ tion of current state and event, and one for pointers to

to every event of í , VTables for state objects of methods that de®ne the actions.

extend the VTables for state objects of í . Hence,

¡ Our technique requires a minimum of one-and- the CVTables of are an extension of the CVTable half times the space of standard table method for the

of í , in that for every state-event combination of

¡ CVTable, plus space for StateMaps and IVTables. In

í , there is one for . Furthermore, there is no

¡ the worst case, every combination of source state and additional overhead to lookup the CVTable of .

event needs its own StateMap. Additionally, each í

STATEMAP Suppose that a transition 6 of is mapped StateMap might contain entries for every single state

¡

: j +

to some transitions + and of . As long as the in the base machine. Similarly, in the worst case, every :

subclassing does not increase non-determinacy, + method may invoke all methods of all states. How- j

and + have different source states. So we create ever, usually StateMaps and IVTables can be shared,

two copies of the StateMap used for 6 for each and do not refer to every other state and method, so we derived source state, and replace the destination as need little space. For example, in Figure 5, we need required. Thus, the tables are extensions with no only two StateMaps with four entries each, although extra lookup overhead. the derived machine has four states, each with three new methods. Also, some space is saved due to code IVTABLE IVTables are like StateMaps, except that reuse. they point to methods. Thus, the IVTables can be extended just like StateMaps.

µ 

@ bc¹§¨ © g©%¡ § @ descriptions with support for subclassing, composi- tion, etc. C++ code for all of the virtual memory state As we have seen, the StateMap technique cannot com- machines described in the paper is generated automat- pletely eliminate method rede®nition for non-determi- ically. Compared to the original non-object-oriented nistic transitions. A more pragmatic limitation is implementation of VM and DVM, the equivalent new that for our C++ like [7] implementation, the struc- implementation requires only half as many lines of ture of state machines must be statically declared. Of generated C++ code. For new protocols, reuse is even course, a more dynamic Smalltalk like implementa- greater, so that our latest implementation supports sev- tion is straightforward to build. eral new protocols but is still smaller than the original.

The input to the generator is only 40% of the generated

k  ¨m 

¢  § o¨k k° oHg§*©%£gI§QZ*§#¥¨©C´j£g ¥ o'§R©%ogW§ © g©

code, since it consists mostly of the method code and

 m 

©%o'§¥  o o  g©# § eschews C++ declarations and other repetitive code. We are also developing a graphical version of the gen- This section summarizes some issues that are not dis- erator.

cussed in detail due to space restrictions. More details

nNogk° ¨©%ogmg F d

may be found in [22]. l

i gm  i

F¥g©@´£g  #¥g§R©%¡© g©% F¥gIk°¡©C´ The de®nitions The rei®cation technique (RT) has been invented many from Section 4.1 enforce structural similarities, but times [16, 6, 14, 13], usually for the purpose of ªchang- we consider behavioral similarities separately using ing the class of an objectº. Behavior abstractions [14] the Liskov-Wing behavioral subtyping [15] approach and Enabled sets [28] introduce become and replace (LWA). Brie¯y, the idea behind LWA is to specify constructions that hint at our general concept of em- state invariants, method pre-and-post conditions and beddings. Johnson and Zweig [13] and Liu [16] have history properties of state transitions, and show that applied RT program network protocols. Liu also sug- derived machines respect the properties of the base gests the use of a CVTable. The relation between machine. For example, the VM machine (Figure 1) states and classes is explored in [20]. A discussion states have the invariant that ªa virtual page is either similar to that in Section 2 is found in [18]. Taival- mapped to only one physical page, or not mapped saari [27] suggests that objects have modes, and tran- at allº. Clearly, the COW machine (Figure 2) states sitions between modes are governed by a transition respect this invariant. Similarly, we can specify the function. Chambers' predicate classes [4] are similar other properties to prove that a COW machine IS- to modes or states but more dynamic. Our implemen- A VM machine. This technique can be extended for tation technique can be extended to predicate classes composition to show that the DVM machine IS-A VM using methods that automatically select the next state. machine. In particular, our de®nitions of subclassing, composi-

tion, etc., can be applied with predicate classes, and

i

C*oH§ ©%o¨ ©% ¨©%o'§ The implementation technique from easily admit more dynamic implementations. An early Section 5 can be extended to program nested states version of subclassable state machines was described as in StateCharts [10]. Essentially, superstates with in [23]. nested states can be treated as a collection of states. Thus, each state in the collection is represented using Our object-oriented constructions extend Harel's tables as in Section 5, and the tables are switched at StateCharts [10]. Other object-oriented extensions run-time to represent nested state transitions. include ObjectCharts [5], ROOMCharts [25], DisCo

[12], ObjCharts [9], etc. In ObjectCharts, ROOM-

 

¤¦¨©%§ ¨©%og ²fo oj  ¨©%¡ We have programmed a Charts and ObjCharts, state machines are inherited by simple yacc-like generator that takes state machine adding new states and actions, or by re®ning exist- ing actions. Substitutability is achieved essentially by requiring that the subtype traces should extend the be- and critiqued several versions of this paper. Prof. havior of the parent. In DisCo, inheritance is de®ned Michael Loui, Ellard Roush, Amitabh Dave,Mohlale® as importing class de®nitions. Se®ka, Tin Qian, David Putzolu, Mark Monnin, Brian In contrast, our approach parallels that used in stan- Foote and Don Roberts helped improve the presen- dard object-orientation Ð we de®ne a notion of Self tation. Hermann HuniÈ and Antoni Bieri commented that (1) is a guide for modi®cations and reasoning, on an earlier version of this paper. We also thank the (2) makes constructions such as delegation natural, anonymous referees for helpful comments.

and (3) leads to a highly ef®cient implementation tech-

 oH§ nique. Further, we use the simple Liskov-Wing be- nNoc¤-o o havioral subtyping (Section 6) as opposed to traces. However, unlike StateCharts, etc., at present we do [1] M. J. Bach. The Design of the UNIX operating not consider concurrency. system. Prentice Hall, Englewood Cliffs, New

Jersey, 1986.

n ­  

 ckI¨§ ¡ [2] Grady Booch. Object-oriented Analysis and De- sign with Applications. Benjamin/Cummings, We have described what appears to be the ®rst gen- California, 1994. eral de®nition of inheritance in state machines; its distinguishing features are our notion of Self for state [3] R.H. Campbell. The Speci®cation of process machines, and the concept of Embeddings. With our synchronization by Path-Expressions. In Lecture technique, state machine designers may easily con- Notes in Computer Science, pages 89±102, 1974. struct complex state machines using object-oriented [4] Craig Chambers. Predicate classes. In Pro- techniques, while sharing code for actions. Our ef- ceedings of the European Conference on Object- ®cient implementation technique permits the use of Oriented Programming, July 1993. complex hierarchies in practice. Event dispatch with our approach is only slightly more expensive than a [5] Derek Coleman, Fiona Hayes, and Stephen Bear. C++ virtual function dispatch. Introducing Objectcharts or how to use State- The techniques presented in this paper open further charts in object-oriented design. IEEE Transac- avenues of investigation. For instance, we have found tions on Software Engineering, 18(1):9±18, Jan- simple solutions to the so-called inheritance anomaly uary 1992. [17] based on state machine inheritance. Our notion [6] Stephen R. Davis. C++ objects that change their of Self seems to lead naturally to recursively typed types. The Journal of Object-Oriented Program- extensions of Nierstrasz's regular types [19] and in- ming, pages 27±32, July/August 1992. heritance in path expressions [3]. State machines are used in specifying interfaces [29], so subclassing or [7] Margaret Ellis and Bjarne Stroustrup. The C++ composition of interfaces might be investigated using Annotated Reference Manual. Addison-Wesley our de®nitions. It may be possible to apply our notion Publishing Company, Reading, Massachusetts, of Self to frameworks, where objects are interrelated 1990. by relationships other than BECOMES-A.Besides our [8] Erich Gamma, Richard Helm, Ralph Johnson, four constructions, it may be interesting to consider and John Vlissides. Design Patterns: Ele- higher-order state machines that manipulate other ma- ments of Object-Oriented Software Architecture. chines. Finally, work remains to be done in adapting Addison-Wesley Publishing Company, Reading, state machine design tools for object-oriented designs. Massachusetts, 1994. Expressing embeddings graphically might be an inter- esting challenge. [9] Dipayan Gangopadhyay and Subrata Mitra. Ob- jChart: Tangible speci®cation of reactive ob- Acknowledgments Prof. Ralph Johnson taught us RT ject behavior. In Proceedings of the Euro- pean Conference on Object-Oriented Program- [18] John D. McGregor and Douglas M. Dyer. A note ming, number 707 in Lecture Notes in Computer on inheritance and state machines. ACM Sigsoft Science, pages 432±457. Springer-Verlag, New Notes, 1994. York, 1993. [19] Oscar Nierstrasz. Regular types for active ob- [10] David Harel. Statecharts: A visual formalism jects. In Proceedings of the Conference on for complex systems. Science of Computer Pro- Object-Oriented Programming Systems, Lan- gramming, pages 231±274, August 1987. guages and Applications (OOPSLA'93), vol- ume 28 of SIGPLAN Notices, pages 1±15. ACM [11] John E. Hopcroft and Jeffrey D. Ullman. In- Press, October 1993. troduction to Automata Theory, Languages and Computation. Addison-Wesley Publishing Com- [20] Alexander S. Ran. Modelling states as classes. pany, Reading, Massachusetts, 1988. In Proceedings of the Technology of Object- [12] Hannu-Matti JarvinenÈ and Reino Kurki-Suonio. Oriented Languages and Systems Conference, DisCo speci®cation language: Marriage of ac- 1994. tions and objects. In International Conference [21] James Rumbaugh, Michael Blaha, William Pre- on Distributed Computing Systems, pages 142± merlani, Frederick Eddy, and William Lorensen. 157, 1991. Object-Oriented Modeling and Design. Prentice [13] Ralph E. Johnson and Jonathan M. Zweig. Del- Hall, Englewood Cliffs, New Jersey, 1991. egation in C++. The Journal of Object-Oriented [22] Aamod Sane. Object-Oriented State Ma- Programming, pages 31±34, Nov/Dec 1991. chines: Subclassing, Composition, Delega- [14] Dennis G. Kafura and Keung Hae Lee. In- tion, and Genericity. Technical report, De- heritance in actor based concurrent object ori- partment of Computer Science, University of ented languages. In Proceedings of the Euro- Illinois at Urbana-Champaign, 1994. See pean Conference on Object-Oriented Program- http://choices.cs.uiuc.edu/sane/home.html. ming (ECOOP'89), pages 131±145. Cambridge [23] Aamod Sane and Roy Campbell. Subclassing University Press, 1989. state machines. Technical Report UIUCDCS-R- [15] Barbara Liskov and Jeanette M. Wing. A be- 92-1773, Department of Computer Science, Uni- havioral notion of subtyping. ACM Transactions versity of Illinois at Urbana-Champaign, 1992. on Programming Languages and Systems (to ap- [24] Aamod Sane, Ken MacGregor, and Roy Camp- pear), 1994. Available from bell. Distributed virtual memory consistency http://www.cs.cmu.edu:8001/afs/cs/user/ protocols: Design and performance. In Sec- wing/www/home.html. ond IEEE workshop on Experimental Distributed [16] Chung-Syan Liu. An object-based approach to Systems, 1990. protocol software implementation. In Sympo- [25] Bran Selic. An ef®cient object-oriented varia- sium on Communications Architectures and Pro- tion of the Statecharts formalism for distributed tocols (SIGCOMM), pages 307±316, 1994. real-time systems. In CHDL'93 IFIP Conference [17] Satoshi Matsuoka, Kenjiro Taura, and Akinori on Hardware Description Languages and Their Yonezawa. Highly ef®cient and encapsulated applications, pages 26±28, April 1993. re-use of synchronization code in concurrent [26] Sally Shlaer and Stephen J. Mellor. Object Life- object-oriented languages. In Proceedings of the cycles: Modeling the World in States. Yourdon Conference on Object-Oriented Programming Press Computing Series.Yourdon Press (Prentice Systems, Languages and Applications (OOP- Hall, Englewood Cliffs, New Jersey), 1992. SLA'93), volume 28 of SIGPLAN Notices, pages 109±126. ACM Press, October 1993. [27] Antero Taivalsaari. Object-oriented program- ming with modes. The Journal of Object- Oriented Programming, pages 25±32, June 1993. [28] Chris Tomlinson and Vineet Singh. Inheritance and synchronization with enabled-sets. In Pro- ceedings of the Conference on Object-Oriented Programming Systems, Languages and Applica- tions (OOPSLA'89), SIGPLAN Notices, pages 103±112. Association for Computing Machinery, ACM Press, October 1989. [29] Daniel M. Yellin and Robert E. Strom. Inter- faces, protocols, and the semi-automatic con- struction of software adaptors. In Proceedings of the Conference on Object-Oriented Program- ming Systems, Languages and Applications 94, pages 176±190, 1994.