22.07.2013 Views

UML Action Semantics Action Semantics Consortium ... - MSDL

UML Action Semantics Action Semantics Consortium ... - MSDL

UML Action Semantics Action Semantics Consortium ... - MSDL

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>UML</strong> <strong>Action</strong> <strong>Semantics</strong><br />

<strong>Action</strong> <strong>Semantics</strong> <strong>Consortium</strong><br />

Proposal Version 9<br />

17 December 1999<br />

title.fm Version 9 January 17, 2000 6:41 pm i


title.fm Version 9 January 17, 2000 6:41 pm ii


Contents<br />

Contents<br />

Preface ix<br />

Part I. Summary of Proposal 1<br />

1. <strong>Action</strong> <strong>Semantics</strong> Overview 3<br />

1.1 <strong>Action</strong> Specification Metamodel 3<br />

1.2 Execution Model 3<br />

1.3 <strong>Action</strong> <strong>Semantics</strong> 3<br />

1.4 General Principles 4<br />

Part II. Execution <strong>Semantics</strong> 5<br />

2. Execution Instance Model 7<br />

2.1 Overview 7<br />

2.2 Identities and Snapshots 7<br />

2.3 Links 8<br />

2.4 Objects 9<br />

2.5 Instance Classes 10<br />

AttributeValue 10<br />

DataValueIdentity 11<br />

Identity 11<br />

InstanceIdentity 11<br />

LinkEndValue 11<br />

LinkIdentity 12<br />

LinkObjectIdentity 12<br />

ObjectIdentity 12<br />

ObjectSnapshot 13<br />

Snapshot 14<br />

3. Execution Activation Model 15<br />

3.1 Contents of the activation model 15<br />

3.2 Execution semantics summary 16<br />

3.3 Activation Classes 19<br />

Activation 19<br />

ClauseToken 19<br />

GroupToken 20<br />

ConditionToken 20<br />

ConditionalToken 20<br />

LoopToken 21<br />

Token 21<br />

4. Advanced Execution Mechanisms 23<br />

4.1 Exceptions 23<br />

4.2 Interrupts 23<br />

4.3 Primitive Intertoken Communication 24<br />

4.4 Advanced Execution Classes 24<br />

<strong>Action</strong> <strong>Semantics</strong>TOC.fm Version 9 December 17, 1999 5:09 pm iii


Contents<br />

SimpleQueue 24<br />

5. State Machine Execution 27<br />

5.1 Active Objects 27<br />

5.2 Call events 27<br />

5.3 Interobject Communication 27<br />

5.4 State machines and event processing 27<br />

5.5 State Machine Execution Classes 28<br />

EventInstance 29<br />

SignalInstance 29<br />

Part III. <strong>Action</strong>s 31<br />

6. <strong>Action</strong> Foundation 33<br />

6.1 Overview 33<br />

6.2 Summary 33<br />

6.3 Foundation Classes 37<br />

<strong>Action</strong> 37<br />

ControlFlow 38<br />

DataFlow 38<br />

InputPin 39<br />

OutputPin 39<br />

Pin 39<br />

Primitive<strong>Action</strong> 40<br />

Procedure 40<br />

7. Composite <strong>Action</strong>s 41<br />

7.1 Group <strong>Action</strong> 41<br />

7.2 Conditional <strong>Action</strong> 43<br />

7.3 Loop <strong>Action</strong> 45<br />

7.4 Concurrent Collection <strong>Action</strong>s 46<br />

7.5 Composite Classes 46<br />

Clause 46<br />

Conditional<strong>Action</strong> 47<br />

Group<strong>Action</strong> 49<br />

Loop<strong>Action</strong> 51<br />

Map<strong>Action</strong> 52<br />

Reduce<strong>Action</strong> 52<br />

8. Access <strong>Action</strong>s 55<br />

8.1 Read <strong>Action</strong>s 55<br />

8.2 Write <strong>Action</strong>s 55<br />

8.3 Access Classes 55<br />

ReadAssociation<strong>Action</strong> 56<br />

ReadAttribute<strong>Action</strong> 56<br />

WriteAssociation<strong>Action</strong> 56<br />

WriteAttribute<strong>Action</strong> 57<br />

9. Manipulation <strong>Action</strong>s 59<br />

<strong>Action</strong> <strong>Semantics</strong>TOC.fm Version 9 December 17, 1999 5:09 pm iv


Contents<br />

9.1 Manipulation Classes 59<br />

CreateLink<strong>Action</strong> 60<br />

CreateObject<strong>Action</strong> 60<br />

DestroyLink<strong>Action</strong> 61<br />

DestroyObject<strong>Action</strong> 61<br />

FindLink<strong>Action</strong> 62<br />

ManipulateLink<strong>Action</strong> (abstract) 62<br />

10. Computation <strong>Action</strong>s 63<br />

10.1 Computation Classes 63<br />

ApplyFunction<strong>Action</strong> 63<br />

Code<strong>Action</strong> 64<br />

LiteralValue<strong>Action</strong> 65<br />

Null<strong>Action</strong> 65<br />

11. Interaction <strong>Action</strong>s 67<br />

11.1 Interaction Classes 67<br />

Call<strong>Action</strong> 68<br />

Call return (implicit action) 69<br />

Interrupt<strong>Action</strong> 69<br />

Raise<strong>Action</strong> 70<br />

Send<strong>Action</strong> 70<br />

Signal (from core) 71<br />

Spawn<strong>Action</strong> 71<br />

Terminate<strong>Action</strong> 71<br />

Watch<strong>Action</strong> 72<br />

12. Primitive Communication <strong>Action</strong>s 73<br />

12.1 Primitive Communication Classes 73<br />

Notify<strong>Action</strong> 73<br />

Poll<strong>Action</strong> 74<br />

Wait<strong>Action</strong> 74<br />

13. Exception <strong>Action</strong>s 75<br />

13.1 Exception and Interrupt Handling Classes 75<br />

Exception<strong>Action</strong> (implicit) 75<br />

Interrupt<strong>Action</strong> 75<br />

Kill<strong>Action</strong> 76<br />

Raise<strong>Action</strong> 76<br />

Part IV. Appendices 77<br />

A Examples of Program Specifications 79<br />

Index 81<br />

<strong>Action</strong> <strong>Semantics</strong>TOC.fm Version 9 December 17, 1999 5:09 pm v


Contents<br />

<strong>Action</strong> <strong>Semantics</strong>TOC.fm Version 9 December 17, 1999 5:09 pm vi


Table of Figures<br />

Table of Figures<br />

Figure 1. Snapshot and identity execution model 8<br />

Figure 2. Link execution model 9<br />

Figure 3. Object execution model 10<br />

Figure 4. <strong>Action</strong> and pins 33<br />

Figure 5. Data flow 34<br />

Figure 6. Control flow 34<br />

Figure 7. Data flows across composite action boundary 35<br />

Figure 8. Available inputs and outputs of composite action 35<br />

Figure 9. Procedure with pins and action 36<br />

Figure 10. <strong>Action</strong> foundation metamodel 37<br />

Figure 11. Group action and its flows 41<br />

Figure 12. Conditional action and pins 43<br />

Figure 13. Loop and pins 45<br />

Figure 14. Composite actions metamodel 46<br />

Figure 15. Access classes metamodel 55<br />

Figure 16. Manipulation classes metamodel 59<br />

Figure 17. Computation classes metamodel 63<br />

Figure 18. Interaction classes metamodel 67<br />

Figure 19. Primitive communication classes metamodel 73<br />

Figure 20. Exception and interrupt handling classes 75<br />

<strong>Action</strong> <strong>Semantics</strong>LOF.fm Version 9 January 17, 2000 6:38 pm vii


Table of Figures<br />

<strong>Action</strong> <strong>Semantics</strong>LOF.fm Version 9 January 17, 2000 6:38 pm viii


Preface<br />

The preface starts here. Do not delete the previous two paragraphs, which reset Framemaker counters.<br />

preface.fm Version 9 December 17, 1999 4:16 pm ix


preface.fm Version 9 December 17, 1999 4:16 pm x


I Summary of Proposal<br />

Part I. Summary of Proposal<br />

This part summarizes the action semantics proposal.<br />

part-summary.fm Version 9 December 17, 1999 5:00 pm 1


I Summary of Proposal<br />

part-summary.fm Version 9 December 17, 1999 5:00 pm 2


1 <strong>Action</strong> <strong>Semantics</strong> Overview 1.1 <strong>Action</strong> Specification Metamodel<br />

Chapter 1. <strong>Action</strong> <strong>Semantics</strong> Overview<br />

Currently the <strong>UML</strong> metamodel is able to construct system models, which are fully adequate for declaring and generating<br />

static structures, but it is incomplete and vague regarding the specification and semantics of executable actions.<br />

The action semantics proposal remedies that lack. The action semantics specification requires 3 additional parts:<br />

1.1. <strong>Action</strong> Specification Metamodel<br />

An extension to the <strong>UML</strong> 1.3 metamodel that expands on the kinds of actions and their structure sufficient to specify<br />

executable actions to all necessary detail. Mainly a listing of actions and their parameters. Class <strong>Action</strong> itself has been<br />

altered. Additional classes have been added to get all of the parameterization right. Stubs (such as <strong>Action</strong>::recurrence)<br />

in the original <strong>UML</strong> 1.3 specification have been removed and replaced with action subclasses.<br />

Additional clarifications may be needed on state machines as well, but they have not yet been provided. The goal<br />

is to support all behavioral concepts, including state machine transitions, in terms of actions, so that the semantics can<br />

be unambiguously defined.<br />

The program (an informal term used in this document) includes instance of the actions specified in this document.<br />

The program forms part of the overall system model, which describes the structure and behavior of a system.<br />

Users create system models that include action specifications. Another phrase for program is behavioral specification,<br />

but this leaves an ambiguity about whether we are specifying the behavior of a particular model or the behavior<br />

mechanisms in general.<br />

We regard state machines and actions as two different but equivalent ways of expressing computation. In practice,<br />

both are useful, but the semantics of either can be expressed in terms of the other. In this document, we (eventually<br />

will) show how to express state machines as actions. This appears simpler, because a state-machine-based<br />

approach would ultimately require some primitive actions, but an action-based approach does not require state<br />

machines. <strong>UML</strong> state machines are regarded as a high-level concept, as they involve considerable complexity and<br />

internal synchronization.<br />

1.2. Execution Model<br />

A new, separate <strong>UML</strong> execution model (not a metamodel!) defines the state of a run-time system and relates it to the<br />

action specification. Users do not use the execution model directly to specify run-time systems. Run-time systems are<br />

created from the system model by execution semantics engines in accordance with the execution semantics rules. The<br />

execution model includes objects, links, and their attributes, as well as the run-time structure of active objects, activations,<br />

and tokens (the mechanisms that make execution work).<br />

Note that users can create models showing snapshots and scenarios that illustrate the execution of systems. The<br />

form of these illustrative models is similar to or isomorphic to the structure of the run-time system, but they are models<br />

designed by a user, whereas the run-time system is a living thing that evolves according to the execution semantics<br />

rules. We will not discuss or build the metamodel for illustrative models in this proposal, although a simple mapping<br />

is possible.<br />

In this proposal we define a foundational model that can support many different physical computer architectures<br />

(SISD, SIMD, MIMD, data flow, and so on). Some of the constructs might seem unusual to many people, but the<br />

intent is to define the fundamental semantics of concurrent execution without making unnecessary assumptions about<br />

the physical architecture (because we want to model them all), while not creating a model that is too abstract for<br />

actual use. In the responses to the Real-Time <strong>Semantics</strong> RFPs, we would expect to layer one or more models of the<br />

physical machine architecture on top of the semantic model proposed here. We do not describe the physical model in<br />

this document, but we have tried to avoid making the mapping to a physical model difficult.<br />

1.3. <strong>Action</strong> <strong>Semantics</strong><br />

For each action, must specify how the state of the system is transformed.<br />

overview.fm Version 9 December 17, 1999 5:00 pm 3


1 <strong>Action</strong> <strong>Semantics</strong> Overview 1.4 General Principles<br />

The specification will be in terms of primitive actions on local fragments. Need to tell how they assemble into<br />

larger systems and actions. The issue of conflict must be addressed (but not removed). Nondeterminism is permissible<br />

when necessary.<br />

Physically this description is packaged with the definition of each action and expressed as precondition-postcondition<br />

pairs.<br />

1.4. General Principles<br />

Provide a logical model of computation without forcing it into a particular implementation or hardware architecture.<br />

Try to capture the essence of computation.<br />

The logical model can be mapped into various physical computer architectures. One of these is the conventional<br />

Von Neumann SISD computer with a processor and a memory, but there are many others that are becoming more<br />

important, and we do not want to assume the conventional computer. We don’t want to make it inefficient to model,<br />

either.<br />

The logical model must be overlayable by physical models of computers for real time and other purposes. It is<br />

not our purpose to provide the overlays here but only to make them possible.<br />

Concurrency and distribution are becoming extremely important, although standard languages and computer<br />

architectures are still somewhat lagging. Model concurrency and distribution in the most general way, without making<br />

assumptions that won’t scale up. No assumption of centrality or global synchronicity is permissible.<br />

Actual programs sometimes fail to terminate, have bugs, and cause problems. Means must be provided to clean<br />

up erroneous executions. This is messy but necessary and involves issues such as killing processes, exception handling,<br />

and interrupting other processes.<br />

Practical computation in the presence of concurrency requires accepting the possibility of conflict. To prevent it<br />

in the architecture is not practical.<br />

We must support conventional programming languages, particularly the concept of calls, although they are tricky<br />

in the presence of concurrency and distribution.<br />

Both coarse-scale and fine-scale concurrency must be modeled, but not necessarily in the same way. They will be<br />

implemented differently on all but experimental machines.<br />

Low-level primitives should separate computation and memory access so that they can be cleanly mapped to a<br />

physical model.<br />

The set of primitive functions should not be limited but should be extensible, although this creates some problems<br />

for interchangeability, because we don’t want to be defining a programming language.<br />

Compilers will map from convenient syntax and constructs to the action semantics constructs. We don’t need to<br />

provide sugarings for all useful things.<br />

The fundamental semantics should be expressed in terms of simple primitive behavioral concepts. Complicated<br />

constructs should be treated as high-level concepts and mapped into the primitive concepts. Users would not necessarily<br />

work in terms of all the primitive concepts. Primitive concepts should be simple logically, should have precise<br />

semantics, and should be conceptually simple to implement.<br />

overview.fm Version 9 December 17, 1999 5:00 pm 4


II Execution <strong>Semantics</strong><br />

Part II. Execution <strong>Semantics</strong><br />

During execution the run-time system state is a set of objects, links, activations, and tokens, each of which may contain<br />

values, including references (pointers to objects). The objects and links together define the data set of the system.<br />

The data set is consistent with the <strong>UML</strong> static model for the given system. Its form is specified by the execution<br />

instance model defined in this document. The active objects, activations, and tokens define the control set of the system.<br />

The control set is consistent with the program model for the given system. Its form is specified by the execution<br />

activation model defined in this document. The entire run-time system state evolves over time in accordance with the<br />

execution semantics rules defined in this document. The execution model is the model for the run-time system state.<br />

The complete description of an executing system includes its system model, consisting of classes, methods, state<br />

machines, and the like; and the run-time system state, consisting of objects, links, active objects, activations, and<br />

tokens. Many values in the run-time system state reference elements in the system model (e.g., the class of an object,<br />

the type of a value, the method or state where an activation is executing, and so on).<br />

There are four chapters in this part. Chapter 2, “Execution Instance Model”, describes the run-time instance data<br />

that corresponds to a class model for a system. Chapter 3, “Execution Model”, describes the internal structure needed<br />

to support dynamic execution of actions. Chapter 4, “Advanced Execution Mechanisms”, describes the exception and<br />

interrupt handling mechanisms. Chapter 5, “State Machine Execution”, describes the state machine and active object<br />

execution model.<br />

part-execution.fm Version 9 January 17, 2000 6:38 pm 5


II Execution <strong>Semantics</strong><br />

part-execution.fm Version 9 January 17, 2000 6:38 pm 6


2 Execution Instance Model 2.1 Overview<br />

2.1. Overview<br />

Chapter 2. Execution Instance Model<br />

The execution model is our basic formalism for defining the semantics of <strong>UML</strong> actions (and, potentially, other behavioral<br />

constructs). The primary portion of this model, common to the denotational and operational approaches to defining<br />

the <strong>UML</strong> dynamic semantics, is the definition of the information that must be maintained at any one point in time<br />

by a “virtual machine” executing a <strong>UML</strong> model. This portion can be further divided into two parts: the execution<br />

instance model, which defines the structure of instances and links conforming to classes and associations in the model<br />

being executed, and the execution activation model, which defines the information that must be maintained regarding<br />

the execution of an action itself.<br />

This chapter focuses on the execution instance model. Each of the following sections provides an overview discussion<br />

of a portion of this model together with a class diagram for this portion. The classes for all portions are<br />

described together in a single alphabetical list at the end of the chapter. Generally, classes in the structure model have<br />

associations with metaclasses in the <strong>UML</strong> metamodel. The formal connection of the structure model to the <strong>UML</strong><br />

metamodel is provided by conformance rules that constrain the relationship of instances of structure model classes to<br />

associated instances of <strong>UML</strong> metaclasses.<br />

Note. Like the well-formedness rules of the <strong>UML</strong> metamodel, the conformance rules here must ultimately<br />

be formally expressed using OCL. This is yet to be done, though.<br />

2.2. Identities and Snapshots<br />

Execution deals with instances and links whose structure is specified by classifiers and associations. Each of these<br />

“entities” has a unique identity that is immutable over time. However, of these entities, objects are mutable and have<br />

properties that change over time. An object snapshot is a view of an object at any one point in time, with the specific<br />

values at that time for all object properties. (Object snapshots are the only kind of snapshots in the structure model,<br />

but the general concept of a “snapshot” is also used in the activation model.)<br />

The idea that a snapshot represents a single point in time is crucial here. One cannot introduce the idea of something<br />

“changing over time” directly into the static semantic model without ending up with a circular definition of<br />

dynamic semantics. (This circularity can be avoided in the case of strictly static semantics by mapping the static<br />

semantic <strong>UML</strong> modeling constructs to the usual set-theoretic semantic representation.)<br />

Nevertheless, one can still think of the entity as “changing over time.” A sequence of such snapshots form a history<br />

of the entity over time. Intuitively, one can think of viewing this sequence over time like a movie, giving the mental<br />

picture of a single entity with changing properties over the course of its history. (These ideas will be formalized in<br />

the dynamic semantic model.)<br />

Another important corollary is that it is not possible to directly navigate from an identity to a snapshot, since<br />

there is no distinguished “current” snapshot in the history of an entity. Indeed, dereferencing an identity to yield a current<br />

snapshot is a non-trivial operation requiring a synchronization in time between the snapshot performing the<br />

dereference and the snapshot resulting from the dereference. (This will also dealt with formally in the dynamic<br />

semantic model.)<br />

It is important to distinguish instance identities from link identities, because it is the instance identities that are<br />

the values of attributes and association ends. It is further necessary to distinguish data-value identities from object<br />

identities, because a data value is immutably associated with a single data type, while an object can have multiple<br />

classifiers that can change over time (allowing for multiple and dynamic classification). Thus, the data type of a data<br />

value can be associated directly with its identity, while the classifiers of an object must be associated with its snapshot.<br />

executionInstance.fm Version 9 January 17, 2000 6:39 pm 7


2 Execution Instance Model 2.3 Links<br />

These basic concepts of identities and snapshots are formalized in the following model.<br />

DataValueIdentity<br />

+type 1<br />

DataType<br />

2.3. Links<br />

*<br />

InstanceIdentity<br />

ObjectIdentity LinkIdentity<br />

ObjectSnapshot<br />

LinkObjectIdentity<br />

Identity<br />

+identity<br />

1<br />

*<br />

Association<br />

Figure 1. Snapshot and identity execution model<br />

A link is related to an association in an analogous manner to the relationship of an instance to its classifier(s). The<br />

link then provides link-end values for the association ends of the association. However, a link is not a mutable entity.<br />

The set of link-end values for a link is part of the very identity of the link, in the sense that a link can basically be<br />

thought of as a tuple of values for the ends of an association.<br />

Further, even though it is conventional to talk of the “creation” and “destruction” of links, the lack of any other<br />

mutating actions makes the concept of a “link snapshot” unnecessary. Instead, a link can be considered to exist as<br />

long as its link-end values are referenced by object snapshots, and it ceases to exist when all object snapshots have<br />

been “unlinked” from it.<br />

executionInstance.fm Version 9 January 17, 2000 6:39 pm 8<br />

*<br />

1<br />

+association<br />

AssociationClass<br />

Snapshot<br />

*<br />

1..*<br />

Classifier<br />

Class<br />

+classifier


2 Execution Instance Model 2.4 Objects<br />

This approach to links is formalized in the following metamodel.<br />

+connection<br />

2.4. Objects<br />

Association<br />

AssociationEnd<br />

+associationEnd 0..1<br />

+qualifier<br />

2..*<br />

Attribute<br />

Object is a mutable entity, that is, one whose properties may change over time. The values of the properties at any one<br />

point in time are given by the snapshot for the object that is effective at that time. The mutable properties of an object<br />

associated with its snapshot include the following.<br />

• The set of classifiers of the object.<br />

1<br />

*<br />

{ordered}<br />

+association<br />

1<br />

*<br />

+attribute<br />

+associationEnd<br />

1 *<br />

1<br />

*<br />

Figure 2. Link execution model<br />

• Values for the attributes specified by all of these classifiers.<br />

Identity<br />

LinkIdentity<br />

+link 1<br />

+linkEndValue 2..*<br />

LinkEndValue<br />

+qualifierValue *<br />

AttributeValue<br />

+predecessor<br />

*<br />

1<br />

• Values for the (navigable) opposite link ends of associations in which the classifiers participate.<br />

InstanceIdentity<br />

Note that we do not include snapshot specializations for other types of mutable instances, such as instances of nodes,<br />

components and use cases. The representation of mutable objects in the execution model presented here is rich<br />

enough to also act as the semantic representation for other mutable instances, with appropriate restrictions (e.g., a<br />

component instance must have a single component as its classifier throughout its history).<br />

A link object has both the properties of a link and the properties of an object. Since there is no link snapshot, the<br />

link properties are all associated with the link-object identity (see Section “Objects” on page 9). Therefore, the mutable<br />

properties of a link object are all object properties that can be represented using an object snapshot.<br />

executionInstance.fm Version 9 January 17, 2000 6:39 pm 9<br />

*<br />

0..1<br />

0..1<br />

0..1<br />

{ordered}<br />

+successor<br />

1<br />

+value<br />

+value


2 Execution Instance Model 2.5 Instance Classes<br />

This concept of an object snapshot is formalized in the following metamodel.<br />

+value 1<br />

InstanceIdentity<br />

+value 1<br />

2.5. Instance Classes<br />

Snapshot<br />

ObjectIdentity<br />

+/objectId<br />

*<br />

1<br />

*<br />

*<br />

LinkEndValue<br />

+linkEnd *<br />

ObjectSnapshot<br />

Figure 3. Object execution model<br />

{ordered}<br />

Association<br />

AssociationEnd<br />

Classifier<br />

Feature<br />

+feature<br />

StructuralFeature<br />

AttributeValue<br />

An attribute value provides a single value for a specific attribute. The value is represented as an instance identity. In<br />

the case of an object identity, this effectively represents a reference to the object, since it is not dependent on the<br />

object snapshot. Note that if the attribute has a multiplicity, then there may be several attribute values for that<br />

attribute, but each attribute value only has a single associated instance identity. (See also Section “Objects” on page 9<br />

on the use of attribute values to represent the values of association-end qualifiers.)<br />

executionInstance.fm Version 9 January 17, 2000 6:39 pm 10<br />

0..1<br />

*<br />

*<br />

AttributeValue<br />

*<br />

1<br />

+associationEnd<br />

*<br />

+attributeValue<br />

*<br />

+classifier<br />

1..*<br />

+attribute<br />

1<br />

2..*<br />

*<br />

1<br />

0..1<br />

*<br />

1<br />

Attribute<br />

+connection<br />

+type<br />

+owner


2 Execution Instance Model 2.5 Instance Classes<br />

Associations<br />

• attribute The attribute whose value is given by this attribute value.<br />

• value The actual instance identity representing a value of the attribute.<br />

Issue. It would seem logical to include here a conformance rule requiring the value of an attribute to have a<br />

classifier that conforms to the type of the attribute. However, objects can be dynamically classified, so it is<br />

not possible in general to determine their classifier(s) from their identity. Instead, any check for type conformance<br />

must be done on assignment of the value to the attribute. If the object is dynamically reclassified,<br />

though, there does not seem to be any good way to assure that it will still necessarily conform to the type of<br />

the attribute.<br />

DataValueIdentity<br />

In <strong>UML</strong>, data values represent “immutable” instances whose properties do not change over time. Indeed, the properties<br />

of a data value are implicit in the identity of the data value itself, so data values do not have snapshots or histories<br />

at all. A data value can have only one classifier, which must be a data type.<br />

Associations<br />

• type The data type of the value represented by this data-value identity.<br />

Identity<br />

The identity of some entity is immutable, timeless and unique from all other identities.<br />

InstanceIdentity<br />

An instance identity is the identity of some instance of a “classifier”.<br />

LinkEndValue<br />

A link-end value provides a single value for a specific end of a link. The value is represented as an instance identity.<br />

In the case of an object identity, this effectively represents a reference to the object, since it is not dependent on the<br />

object snapshot.<br />

If the specified association end has qualifiers, then the link-end value must also include attribute values for each<br />

of the qualifiers. If the association end is ordered, then the link-end value also has links to the previous and/or next<br />

link-end values in the ordering for that end of the link snapshot. (See also Section “Links” on page 8 for the relationship<br />

of link-end values to object snapshots.)<br />

Issue. The instance-level specification of qualifier values is incorrect in the <strong>UML</strong> 1.3 specification. The<br />

association “qualifierValue” is mentioned in the description of LinkEnd, but it is not shown on Figure 2-16<br />

(Common Behavior - Instances and Links) or covered in the well-formedness rules.<br />

Note. It seemed simpler to specify the ordering of link-end values for an ordered association end using a<br />

“linked-list” kind of approach then, say, explicit index attributes.<br />

executionInstance.fm Version 9 January 17, 2000 6:39 pm 11


2 Execution Instance Model 2.5 Instance Classes<br />

Associations<br />

• associationEnd The association end whose value in a link is represented by this link-end value.<br />

• link The identity of the link containing this link-end value.<br />

• predecessor The link-end value for the same association end in a different link for the same association<br />

that represents the value, if any, that precedes this link-end value in an ordered association<br />

end.<br />

• qualifierValue The set of values for qualifiers of the association end.<br />

• successor The link-end value for the same association end in a different link for the same association<br />

that represents the value, if any, that follows this link-end value in an ordered association<br />

end.<br />

• value The actual instance-identity that is the value of this link end.<br />

Conformance rules<br />

[1] Ordering consistency. A link-end value may only have a predecessor or successor if its association end is ordered<br />

and any predecessor or successor must be for the same association end but be in a different link.<br />

[2] Qualifier conformance. For each qualifier of the association end of a link-end value, the link-end value must have<br />

a number of attribute values for that qualifier conforming to the multiplicity of the qualifier and the instanceidentity<br />

values of those attribute values must all be distinct.<br />

LinkIdentity<br />

The identity of a link is determined by the association of the link and by the values the link gives to the association<br />

ends of the association. Therefore, a link identity is associated with both an association and a set of link-end values,<br />

reflecting the immutability of a link. Note that a link has at most one link-end value for each association end of its<br />

association.<br />

Associations<br />

• association The association for the link represented by this link identity.<br />

• linkEndValue The set of values of the ends of the link corresponding to the association ends of the association.<br />

Conformance rules<br />

[1] Association-end conformance. Each link-end value of a link identity must be for a distinct association end of the<br />

association of the link identity and each non-optional association end (i.e., one with a multiplicity lower bound<br />

greater than zero) must have a corresponding link-end.<br />

LinkObjectIdentity<br />

A link object is an instance of an association class, which is both an association and a class. As such, a link-object<br />

identity is both a link identity and an object identity.<br />

ObjectIdentity<br />

An object identity represents the identity of an object or any other mutable instance.<br />

executionInstance.fm Version 9 January 17, 2000 6:39 pm 12


2 Execution Instance Model 2.5 Instance Classes<br />

ObjectSnapshot<br />

An object snapshot represents a snapshot of the properties of an object or any other mutable instance. These properties<br />

include the classifiers of the object, the values of the attributes of the object and the values of the opposite link<br />

ends of the object.<br />

Associations<br />

• attributeValue The set of values for attributes of the classifiers of the object snapshot.<br />

• classifier The set of classifiers of the object represented by the object snapshot.<br />

• linkEnd The set of values for the opposite link ends of navigable association ends of associations in<br />

which classifiers of the object snapshot are involved.<br />

• objectId (Derived) The identity of the object snapshot, as an object identity.<br />

Conformance rules<br />

[1] Object-identity constraint. The identity of an object snapshot must be an object identity.<br />

[2] Multiple-classification constraint. If an object snapshot has more than one classifier, then they must all be<br />

classes.<br />

[3] Attribute conformance. For each attribute owned by each classifier of an object snapshot, there must be a number<br />

of attribute values conforming to the multiplicity of the attribute and the instance-identity value of these attribute<br />

values must all be distinct.<br />

Issue. How are classifier-scope attributes represented?<br />

[4] Association conformance. For each association in which a classifier of an object snapshot is involved, for each<br />

navigable opposite association end of the association, for each distinct set of values for qualifiers of that association<br />

end (if any) there must be a number of link-end values consistent with the multiplicity of that association end<br />

and the instance-identity values of those link-end values must be distinct. If an association end is ordered, then<br />

all the link-end values for that association end, with the same values of any qualifiers of the association end, must<br />

be linked together in a single predecessor/successor list. (See Section “Links” on page 8 for the modeling of<br />

qualifier values and predecessor/successor ordering.)<br />

Issue. This association conformance rule only handles the multiplicity of navigable association ends (whose<br />

link-end values are accessible from object snapshots). One way to handle multiplicity constraints on nonnavigable<br />

ends requires would be to also make the link-end values of non-navigable ends properties of object<br />

snapshots, but this would introduce a coupling to the association that seems unexpected in the absence of<br />

navigability. Alternatively, we could introduce snapshots to represent the extension of the association as a<br />

whole, with multiplicity constraints applying across all the links of the association in existence at any point<br />

in time.<br />

[5] Association-class conformance. If the identity of an object snapshot is a link-object identity, then exactly one of<br />

the classifiers of the object snapshot must be an association class that is the same as the association related to its<br />

identity, otherwise none of the classifiers may be association classes.<br />

Issue. Since the association of a link object is fixed here via its link-object identity, it is not possible for the<br />

link object to be reclassified from one kind of association to another or for a non-link object to be reclassified<br />

as a link object. This does not seem to be too severe a limitation.<br />

executionInstance.fm Version 9 January 17, 2000 6:39 pm 13


2 Execution Instance Model 2.5 Instance Classes<br />

Snapshot<br />

A mutable entity (such as an object, as opposed to a data value) will have a unique identity over its entire lifetime, but<br />

its properties may change over time. A snapshot is a record of a complete set of properties for the entity at a single<br />

instant in time. Note that snapshots do not “change over time” as such. Rather, there is a separate snapshot for each<br />

point in time at which the entity has a different set of properties.<br />

executionInstance.fm Version 9 January 17, 2000 6:39 pm 14


3 Execution Model 3.1 Basic execution semantics<br />

Chapter 3. Execution Model<br />

This chapter describes the model for when actions and their various composite forms execute. Any implementation<br />

that has the same effect is compliant, regardless of its actually implementation.<br />

An action, as it appears on a <strong>UML</strong> model, is a specification for a desired execution. Each appearance of the “same”<br />

action appears as two instances in the repository because each appearance is a separate specification for a desired execution.<br />

Consequently, each appearance is, in fact, a separate action; more precisely, an action-as-specified.<br />

At run time, however, each action-as-specified may be executed zero, one or more times. For example, an action<br />

may be guarded by a conditional that is not true, and so it never runs. Separately, each instance of a class may have its<br />

own state machine, which means that an action-as-specification appearing once on the state chart may be in execution<br />

multiple times at the same time, once for each state machine. An action-in-execution is therefore a different concept<br />

from an action-as-specified. Each action-as-specified appears as a separate instance in the metamodel; each action-inexecution<br />

appears only at run-time, possibly on different processors.<br />

We use the term <strong>Action</strong> to refer to an action-as-specified and <strong>Action</strong>X for action-in-execution. [Several terms<br />

have been proposed for the action-in-execution, including Token and <strong>Action</strong> Instance. For ease of making a global<br />

replacement, as there will certainly be discussion on the best term, this chapter uses <strong>Action</strong>X instead of these either of<br />

these terms. If you wish, make a global replacement with your favorite term and see how it reads.] An actionX, then,<br />

is the potential execution of an action. The two concepts cannot be merged because multiple actionXs may be in<br />

(potential) execution at once for a single action.<br />

<strong>Action</strong>s are grouped together for several reasons. The highest-level such grouping is the Procedure, which refers<br />

to a set of actions in a method body, or the set of actions specified to execute on exit from a state, on a transtition, or<br />

on entry to state. Just as an action specifies a desired execution and an actionX is the run-time execution of it, so too<br />

a procedure-as-specified has a corresponding procedure-in-execution, dubbed ProcedureX for parallelism of terminology.<br />

This chapter describes a model for the execution of actionXs, ProcedureXs, and all the intermediate composites<br />

in execution. It does not descibe the composites in specification (See Chapter xx), nor does it describe the context for<br />

how or why a particular ProcedureX is caused to be executed (See Chapter yy).<br />

3.1. Basic execution semantics<br />

When can a ProcedureX execute?<br />

A procedureX executes when a method is invoked or when an event triggers a transition. The details are described in<br />

Chapter yy.<br />

When a procedureX starts execution, it has available to it the arguments passed in with the call, or the arguments<br />

supplied with the event. These data items may be viewed as data flows, and they are made available to all actions<br />

within the procedure. In addition, data in the static structure model is available to any (read) action that requires them.<br />

Note: We have used “arguments” for both call arguments and the supplemental data items passed in with an<br />

event. There is some utility in separating the two terms, but in this chapter they are truly identical in their<br />

treatment, though not their specification (which is not in this chapter, but in Chapter yy.)<br />

Because of the concurrent nature of the action semantics, every action within the procedure may execute at once,<br />

unless otherwise constrained by data flow or explicit control flow. Consequently, every actionX within the procedureX<br />

is enabled as soon as the procedureX is enabled.<br />

Enabled actionXs that have all their inputs can execute immediately. Therefore, enabled actionXs that have no<br />

inputs can execute, as can actions that rely solely on arguments, and all read actions in their various kinds. Stated in<br />

the other way, enabled actionXs that depend on the outputs of other actionXs cannot run until the “upstream”—either<br />

in a data flow or control flow sense—actionXs complete.<br />

executionActivation.fm Version 9 January 7, 2000 8:02 am 15


3 Execution Model 3.1 Basic execution semantics<br />

From the perspective of a “downstream” action, an upstream actionX indicates its completion by generating all<br />

its outputs at once, which are then made available to the downstream actionXs. This, in turn, allows downstream<br />

actionXs to execute, and this continues downstream until the chain of actionXs writes the static model, generates a<br />

signal event, or otherwise produces no outputs of interest to actions in the same procedure.<br />

When the only flows remaining are outputs from the procedure, and no actionXs are executing, the procedureX<br />

is complete. At that point, all the outputs on the flows of the procedure—the output arguments—are made available.<br />

Note that there may still be enabled actionXs within the procedure. However, if all actionXs that produce output have<br />

produced their data, and there is other data flow inside the procedure, no enabled action can ever execute, so the<br />

entire proceedure cannot make further progress, so it must, perforce, be complete.<br />

Note. I find this messy. Better would be to have each action with a single output (tupular) flow which is<br />

either produced or not. That way, we know when the procedureX is complete because it has all its component<br />

output flows. This does not require that every element of a flow is present; the tuple can have nulls.<br />

Note that actionXs within a procedureX execute for an indeterminate but finite time, and therefore complete at<br />

different times, so it is possible for a output flow from the procedureX to hold a value before the entire procedureX<br />

completes. Each flowX is therefore “gated” by the definition of the procedureX and no flowXs are made available<br />

outside the procedureX until the whole procedureX is complete as defined above.<br />

A procedureX therefore exhibits a lifecycle: It is created enabled; it enables all its component actions, which is<br />

equivalent to “executing”; at some point, none of the component actions can execute, and the output flows are loaded.<br />

At this point, the outputs are produced, and the procedureX is complete.<br />

When can an <strong>Action</strong>X execute?<br />

An actionX can execute when it is enabled and when it has all its inputs, both data flows and control flows, if any.<br />

An actionX then executes for an indeterminate time.<br />

Once the actionX has completed execution, it generates all its outputs, both data flows and control flows, if any.<br />

An actionX therefore exhibits a lifecycle: It is created enabled; it executes when it has all its inputs; it executes<br />

and produces its outputs at once; it is then complete and dies.<br />

FlowXs<br />

A control flowX is an explicit sequencing between two actions. Because an actionX cannot execute unless it has<br />

all its inputs, the presence of a control flowX effectively sequences two actions. Similarly, a data flowX represents the<br />

presence of an immutable value for input to some other actionX. And because an actionX can’t execute without all its<br />

inputs, a data flowX also effectively sequences actionXs.<br />

Flows may be produced, though not made available to other actions. For example, if an action generates more<br />

than one flow, no downstream action may execute until the upstream action releases all the flows. Note that this is the<br />

same whether the flows are from an actionX or a procedureX.<br />

Each flowX, then, has a lifecycle: It is created present, released, then it is consumed and destroyed.<br />

The following model describes the classes required. Note that each X has an association with the corresponding<br />

class that captures the specification of the execution.<br />

Note that PinXs are not required. A pin models a specification of a (logical) name for the data flow that is of no use in<br />

execution.<br />

Note: Two simplifications are possible at this point. First, we could redefine data flows in Foundation so that<br />

it means the combination of all the data between two actions. If we do this, we can place all the data elements<br />

on a (combined) flow “at once.” Second, we could make all the data from an action into a single<br />

“cable.” Then we don’t have to deal with all the issues about what “at once” means at any level: either the<br />

whole cableX has a tuple on it or it doesn’t. I prefer the second.<br />

executionActivation.fm Version 9 January 7, 2000 8:02 am 16


3 Execution Model 3.2 Composite <strong>Action</strong>s<br />

3.2. Composite <strong>Action</strong>s<br />

There are several kinds of composite action, each of which is treated in turn.<br />

Group <strong>Action</strong><br />

A group action also has a porous boundary that allows data and control flows to enter and leave the group. The group<br />

action may also be a predecessor and successor in control flows. An input control flow governs the execution of all<br />

actions within the group and is semantically equivalent to a control flow to every action that composes the group.<br />

Similarly, an output control flow from the group indicates that all actions must complete before the successor(s) of<br />

the control flow.<br />

The group-action control flows then are merely shorthands. As Group<strong>Action</strong> is a specialization of <strong>Action</strong>, and<br />

there are no new semantics, there is no need for a corresponding Group<strong>Action</strong>X. Note that this requires a control flow<br />

to or from the Group <strong>Action</strong> to be represented—in the execution model—as control flows to and from the component<br />

actions.<br />

Note: We could choose to model the concept of ‘all actions complete’ in a group, and if so, we should model<br />

it in the same way as a ProcedureX. But then we’d still have to deal with the idea of partial completeness.<br />

Conditional <strong>Action</strong><br />

Like a group action, the combination of flows and actions fully model the contents of a conditional action, and there<br />

are no new semantics.<br />

Note: We could choose to model a Test<strong>Action</strong>X to describe the behavior of the diamond in the conditional.<br />

But all the diamond does is to copy the control flow to another. It would also need a value to make the decision.<br />

It’s better to view the diamond as indicating mutual exclusion of two conditional control flows.<br />

Loop <strong>Action</strong>X<br />

The view modeled so far allows for the execution of an action no more than once, and for a flow to be consumed.<br />

However, a loop requires execution of both test and body more than once. We therefore introduce the concept of a<br />

loopactionX, which controls the execution of the loop.<br />

Because a Loop<strong>Action</strong> is a specifialization of <strong>Action</strong>, we may treat a loop in the same way as all other actions.<br />

For a loop, this means that the test actionX and body actionX (whatever they may be in fact) are both enabled when<br />

the loop actionX is enabled. The flows will arrive when they’re ready. When the body executes, it places the outputs<br />

on the output flows and a single iteration is complete. The outputs are, by default, routed to the back to the actions in<br />

the loop (both test and body), and are treated as the outputs from the loopactionX, though these outputs are not yet<br />

available to downstream actions.<br />

The purpose of the loopactionX is to re-enable the test and the body. When the test fails, as it should eventually,<br />

only then is the loop actionX complete. At that point, the output flows from the loop become available to their consumers.<br />

A loopactionX has a lifecycle: It is created ready; once the clause executes, the loopactionX re-enables the clause<br />

and routes the flows to the test and body actions; once the test fails, the loopactionX allow the body outputs to be<br />

available as the output flows for the entire loop action.<br />

3.3. A note on calls and returns<br />

Calls. A call action comprises a name for an operation, a target object, an ordered list of input pins for the argument<br />

values and an ordered list of output pins for the output argument values. When a call action executes, the called procedure<br />

executes in the “thread” of the caller. More exactly, when the call actionX executes, it is equivalent to executing<br />

the invoked procedureX with the appropriate agruments.<br />

executionActivation.fm Version 9 January 7, 2000 8:02 am 17


3 Execution Model 3.4 Execution Classes<br />

In an object-oriented system, the call action performs a dynamic method lookup based on the class of the target<br />

object and the class hierarchy to determine the actual method, but this merely determines which procedure is executed.<br />

The values of the call arguments are copied into the input pins for the invoked procedureX, and when the<br />

invoked procedureX completes its execution, its output arguments become outputs of the call actionX.<br />

A set of nested calls therefore maps into a set of procedureXs.<br />

Returns. The return pins in a procedure take their values from the output pins of actions in the procedure. All<br />

actionXs in a procedureX must be unable to execute before the procedureX can complete execution. When an procedureX<br />

completes, it and its actionXs cease to exist and the values in the return pins are copied into the output pin of<br />

the calling actionX. The call actionX is then complete and its output values are available to subsequent actions within<br />

the calling procedureX.<br />

Qui faxit? Note that a call is not actually handled by the target object. A conventional procedure call, including OO<br />

method invocations, does not occur in the target object but instead in the thread of control of the caller. The specification<br />

of the procedure exists in the called class, but the execution of the procedureX executes sequentially in the thread<br />

of control of the calling object instance’s state machine.<br />

If the target class is passive (i.e. it has no state chart), the execution of the procedureX exists in the execution<br />

context of the calling active object. If the target class is active, and so has a state chart, then there is the possibility of<br />

data access conflict with the execution of the corresponding state machine. It is the responsibility of the developer to<br />

synchronize the execution of the two state machines, or to be oblivious to the possibility of conflict.<br />

Note. An alternative approach is to use call events. However, in the case that the invoked operation is truly<br />

state independent, there is no need to synchronize. And if it is state-dependent, then the synchronizing mechanisms<br />

of the state chart suffice.<br />

3.4. Execution Classes<br />

These classes define the run-time mechanisms to support execution. They form the execution machinery. They are<br />

not directly accessible by user models; they are created implicitly as part of the execution process. These classes reference<br />

classes in the metamodel and in the user model.<br />

actionX<br />

A potential execution of an action is abstracted as an actionX. Note that this is different from an instance of an action,<br />

which is realized as an instance of the class action in the repository. For any such instance in the respository, there<br />

may be several actionXs, one for each execution—whether actual or pending—at run time.<br />

An actionX has a status value to indicate the progress of executing its action. Normal statuses are enabled (available<br />

to begin execution of the action), executing (in the process of executing the action), and completed (finished executing<br />

the action and waiting to be advanced to the next action).<br />

An actionX does not “advance” to the next action. Rather, its completion permits the execution of successor<br />

actions by generating data and control flowXs. All actionXs are enabled by (some kind of) composite actions that<br />

contain them.<br />

executionActivation.fm Version 9 January 7, 2000 8:02 am 18


3 Execution Model 3.4 Execution Classes<br />

Associations<br />

• guard: ControlFlowX The control flowXs that guard the execution of the actionX.<br />

• source: ControlFlowX The control flowX of which this actionX is the source.<br />

• input: dataFlowX The data flowXs that are input for the execution of the actionX.<br />

• source: dataFlowX The data flowX of which this actionX is the source.<br />

Attributes<br />

• status The state of execution of the actionX. One of:<br />

enabled—available to begin execution<br />

executing—in the process of execution<br />

complete—finished execution<br />

control FlowX<br />

At specification time, an action may produce one or more control flows. At execution time, because there may be several<br />

actions in execution, an actionX may produce one or more control flowXs.<br />

Associations<br />

• receiver: actionX The actionX to which this control flowX is input.<br />

• producer: actionX The actionX that generates this control flowX<br />

Data FlowX<br />

At specification time, an action may produce one or more data flows. At execution time, because there may be several<br />

actions in execution, an actionX may produce one or more data flowXs.<br />

Associations<br />

• receiver: actionX The actionX to which this data flowX is input.<br />

• input: actionX The actionX that generates this data flowX<br />

• receiver: procedureX The procedureX to which this data flowX is input.<br />

• input: procedureX The procedureX that generates this data flowX.<br />

LoopactionX<br />

When a set of actions appear in a loop, the component actions must execute multiple times. Similarly, the flows that<br />

feed these actions and are produced by these actions are reloaded each time round the loop. The machinery that<br />

effects this behavior is abstracted as a loop actionX.<br />

On the first iteration of the loop, the input flowXs are loaded in the normal manner. If the test suceeds and the<br />

loop executes, the outputs from the body become flowXs input to both test and body actionXs. If the test fails, however,<br />

the extant flowXs that are input the the loop action become the outputs of the loop actionX as a whole.<br />

Associations<br />

A loop actionX is a specialization of actionX. No other associations are required—all information about the structure<br />

executionActivation.fm Version 9 January 7, 2000 8:02 am 19


3 Execution Model 3.5 Caboose<br />

of the model is already in Foundation.<br />

Attributes<br />

• status: enum The following status values apply:<br />

enabled—The loop is ready to execute and actionXs are not set up<br />

testing—The while condition is being tested<br />

executing—The body action is being executed<br />

complete—The while condition has evaluated false and the loop execution is<br />

complete<br />

procedureX<br />

A potential execution of a procedure is abstracted as an procedureX. Note that this is different from an instance of an<br />

procedure, which is realized as an instance of the class procedure in the repository. For any such instance in the respository,<br />

there may be several procedureXs, one for each execution—whether actual or pendining—at run time.<br />

An procedureX has a status value to indicate the progress of executing its procedure. Normal statuses are<br />

enabled (available to begin execution of the procedure), executing (in the process of executing the procedure), and<br />

completed (finished executing the procedure and waiting to be advanced to the next procedure).<br />

An procedureX does not “advance” to the next procedure. Rather, its completion permits the execution of successor<br />

procedures. All procedureXs are created by a state machine or a call action in a state machine.<br />

Associations<br />

• receiver: dataFlowX The data flowXs that are input for the execution of the procedureX.<br />

• source: dataFlowX The data flowX of which this procedureX is the source.<br />

Attributes<br />

• status The state of execution of the procedureX. One of:<br />

enabled—available to begin execution<br />

executing—in the process of execution<br />

complete—finished execution, may do another procedure<br />

procedureX<br />

3.5. Caboose<br />

Constraint checking and transactions<br />

<strong>UML</strong> constraints apply at various levels. Some apply at all times, but most can be violated during the actions of a<br />

transition. Some may be valid after certain actions. To do the job right, we need levels of constraint checking, probably<br />

eventually a full transaction mechanism.<br />

A constraint is an action that is conceptually performed between any transitions that affect its referents. We have<br />

to be careful, because there may be many procedureXs and the entire system does not necessarily quiesce, so some<br />

global constraints may be conceptually impossible to apply at times (!). Perhaps constraints can be considered small<br />

procedureXs that simply keep looping and doing the same thing, raising a signal if they find an inconsistency. When<br />

they are to be executed is a question and probably needs to be added to the original metamodel as a user modeling<br />

choice (and maybe a semantic variation point).<br />

Defining the times at which a constraint is evaluated may be difficult. Preconditions and postconditions are<br />

applicable at a definite time, so they are clear. Invariants may prove to be problematical and may need to be avoided<br />

or specified as to when they apply, as they are not usually valid at all intermediate points in a computation.<br />

executionActivation.fm Version 9 January 7, 2000 8:02 am 20


3 Execution Model 3.5 Caboose<br />

In general, the action semantics model will not attempt to verify or enforce user-defined constraints that are made<br />

invalid by actions. (Semantic variations to maintain association multiplicity will be provided as well as automatic<br />

maintenance of composition hierarchies.)<br />

The action semantics will not provide a rollback facility. That is part of the fault tolerance RFP. If conflicts occur,<br />

they may corrupt the data. That’s how real systems work. It is the responsibility of the designer to avoid that. (Using<br />

the to-be-proposed fault tolerance facility is one solution.)<br />

A constraint always involves both data access (read only) and a functional test. Thus it is subject to data access<br />

conflict on reading and must be defined carefully if it involves the reading of multiple values, so that the multiple values<br />

are consistent but we don’t violate causality in obtaining them. However, constraints never modify data (no side<br />

effects), so they can’t affect the course of the computation (unless error signals or exceptions are allowed and occur).<br />

executionActivation.fm Version 9 January 7, 2000 8:02 am 21


3 Execution Model 3.5 Caboose<br />

executionActivation.fm Version 9 January 7, 2000 8:02 am 22


4 Advanced Execution Mechanisms 4.1 Exceptions<br />

Chapter 4. Advanced Execution Mechanisms<br />

This chapter describes classes intended to support advanced forms of control, such as exceptions and interrupts.<br />

These mechanisms operate at the action level (not the state machine level), but their semantics is much more complex<br />

than the primitive execution machinery, and it seems best to separate them. If possible, they should be defined in<br />

terms of the more primitive mechanisms.<br />

4.1. Exceptions<br />

The exception and interrupt handling mechanisms are high-level concepts that can be defined in various ways in<br />

terms of the primitive behavior concepts. They are not part of the fundamental semantics.<br />

Exception handling is a mechanism that deals with occurrences that are difficult to handle with the normal flow<br />

of control of a program. When an exception occurs, the normal flow of control is abandoned and a different flow of<br />

control, specified in the program, is taken. An abnormal occurrence is either a exception or an interrupt.<br />

An exception is a condition that arises synchronously as part of an action, often as an indication that the input<br />

values are inconsistent with the normal mathematical interpretation of the action, for example, taking the square root<br />

of a negative number or attempting to pop an empty stack. An exception could be handled by providing variant outcomes<br />

for the operation, one for each kind of exception as well as one for the normal outcome, but this makes the<br />

code difficult to read and obscures the main flow of control. In normal mathematics it is treated by extending the<br />

result range to be a union of types, but this is often awkward in programming, although this approach is taken in the<br />

IEEE floating point standard (an operation can return values such as NotANumber, Underflow, etc.). Exceptions,<br />

therefore, are not absolutely necessary, but code without them may be very difficult to follow. (Code that misuses<br />

them is also difficult to follow, so they must be used with restraint and care.)<br />

The occurrence of an exception terminates the current action and causes control to progress up the stack of activations<br />

until some activation handles it. This requires a considerable amount of mechanism in the program specification<br />

structure, equal to the mechanisms provided in Ada or C++. An action may have a table of handler actions<br />

indexed by exception kind. If an exception occurs during the execution of the action and the exception index on a handler<br />

matches the kind of exception that occurred (or is an ancestor of it), the handler action receives control. We do<br />

not support handling exceptions and then reexecuting or resuming the action that failed. (This is not supported by<br />

C++ or Ada, either.) Resumption is extremely complicated, not supported by most programming languages, very<br />

implementation dependent, and its effect can be usually be expressed more cleanly without it.<br />

4.2. Interrupts<br />

An interrupt is an asynchronous outside signal independent to the state of execution of an token that affects the flow<br />

of control. Unlike a normal signal, it does not obey run-to-completion semantics. It forces abandonment of the current<br />

execution path and forces the program to take an alternative path specified in the exception structure. This permits the<br />

response to the interrupt to depend on the state of execution, to perform some clean up before exiting, for example.<br />

An interrupt is not subject to run-to-completion processing, in fact, its purpose is often to kill an execution that is out<br />

of control or no longer needed. Interrupts are needed logically, as there is no other way to terminate an unneeded subactivity.<br />

Note that an interrupt handler may raise exceptions to propagate its effects up the call tree. Also, an exception<br />

handler may send an interrupt to notify subordinate tokens. In practice, interrupts and exceptions are closely linked.<br />

A token must be able to kill its dependent activations. This will happen when an active object is killed and its<br />

activations must be cleaned up. A token has a list of pointers to dependent activations so that they can be killed, if<br />

necessary. (We can’t just wait for them to die, because they might not do it.) Therefore the execution of an activation<br />

is not totally synchronous, as it might receive an interrupt signal commanding it to die. Such an interrupt could happen<br />

anywhere within the body of a computation, often leaving the object in a messy state. The exception mechanism<br />

permits a handler to be attached to an action, indicating the exception action to be performed if an interrupt occurs<br />

while tokens are executing in the action. (Often many actions can use the same exception handler.) There must be an<br />

advancedExecution.fm Version 9 December 17, 1999 5:04 pm 23


4 Advanced Execution Mechanisms 4.3 Primitive Intertoken Communication<br />

unconditional kill interrupt, however, in case of an uncooperative activity that refuses to stop even when interrupted.<br />

Such an interrupt cannot be caught.<br />

Permitting activations to be interrupted adds considerable complexity to the execution model, but again there<br />

appears to be no alternative, because the ability will be needed in real applications.<br />

4.3. Primitive Intertoken Communication<br />

4.4. Advanced Execution Classes<br />

Exception<br />

A condition whose occurrence disrupts the normal flow of control of execution and causes a special exception<br />

handling mechanism to be invoked. An exception is a usually synchronous effect of executing an action that indicates<br />

that execution of the action cannot be completed normally. Execution of the action must be abandoned and an exception<br />

handling mechanism attached to nested control actions invoked. An exception may also occur in response to an<br />

interrupt that raises an exception. An exception permits a computation to attempt to recover in a clean, context-dependent<br />

manner. An exception handler is an action attached to an action that deals with the occurrence of a specified<br />

exception during execution of the control action or an action nested within it. Exceptions usually propagate bottomup.<br />

Interrupt<br />

An outside request to modify the flow of control of a computation and invoke a context-dependent action. Execution<br />

of an interrupt handler suspends computation of an action and performs an alternate action that may terminate the<br />

action. Interrupt handling is asynchronous because it can happen at any time. The interrput action can propagate the<br />

interrupt downward, kill the execution, and raise an exception. An interrput permits a computation to respond to an<br />

outside occurrence to in a clean, context-dependent manner. An interrupt handler is an action attached to an action<br />

that deals with the occurrence of a specified interrupt during execution of the control action or an action nested within<br />

it.<br />

SimpleQueue<br />

A primitive container for events that supports low-level communication among tokens and infrastructure interpreters<br />

used to implement higher-level concepts, such as active objects and <strong>UML</strong> state machines. A simple queue only permits<br />

a single reader at one time, but it serializes events added to it concurrently. It provides the fundamental synchronization<br />

concept needed at the low level. This model of waiting is logically simple as well as simple to implement.<br />

The <strong>UML</strong> state machine semantics can be specified by an interpreter that uses Wait and Poll actions on Simple-<br />

Queues.<br />

A SimpleQueue holds events. An action can poll the queue (taking an event, if any, but returning immediately if<br />

there is no event) or wait on the queue (waiting for an event if there is none), but only one action may wait on a queue<br />

at a time. An action may add an event to the queue. Because the queue may be (conceptually or physically) distant<br />

from the token doing the add, such an action may take time to complete. The queue can handle concurrent adding of<br />

events (this is the source of synchronization). The queue maintains the events in the order they arrive, but implementations<br />

may extend the actions to permit events to be added in various locations in the queue or taken from various<br />

locations in the queue.<br />

Associations<br />

• event: EventInstance [0..*]A set of event instances placed on the queue but not yet handled. The events have an<br />

ordering that is maintained, but an implementation may provide action options to add and<br />

advancedExecution.fm Version 9 December 17, 1999 5:04 pm 24


4 Advanced Execution Mechanisms 4.4 Advanced Execution Classes<br />

to remove events in any location, although a first-in first-out policy is consistent and provides<br />

a simple default.<br />

• waiter: Token[0..1] A token that is waiting for an event on the queue (if any). There may only be a single<br />

waiter.<br />

Constraints: event and waiter may not both be nonempty except for a brief while after an event appears on a<br />

previously empty queue (but this may be hard to formalize)<br />

advancedExecution.fm Version 9 December 17, 1999 5:04 pm 25


4 Advanced Execution Mechanisms 4.4 Advanced Execution Classes<br />

advancedExecution.fm Version 9 December 17, 1999 5:04 pm 26


5 State Machine Execution 5.1 Active Objects<br />

Chapter 5. State Machine Execution<br />

We view the system as a collection of collaborating state machine instances. State machines are copies of the state<br />

chart for a class; each state machine is identified by the object to which it belongs, the target object. For the purposes<br />

of the action semantics, orthogonal or concurrent states constitute a separate state machine, also identified with the<br />

object. Objects can also execute method bodies at the same time as executing a state machine.<br />

This chapter describes how the asynchronous behavior of state machines interact with the synchronous invokation<br />

of methods.<br />

5.1. Active Objects<br />

An active object is an object with a state machine; a passive object is one without. Both active and passive objects<br />

(collectively, objects) may execute method bodies at any time when called by another (active) object, even if they are<br />

executing actions associated with a state machine. All activity in a system is therefore ultimately traceable to active<br />

objects.<br />

An action may send an asynchronous signal event to an active object. Each active object has its own (logical)<br />

event queue. When a signal arrives at an active object, it is added to the event queue of the active object. An active<br />

object chooses when to remove an event from the queue. When the active object dequeues an event, it may initiate a<br />

chain of procedures, each of which receive a copy of the data associated with the event as input. Only when the entire<br />

chain of activity is complete does the active object take another event from the queue.<br />

Sequencing constraints are imposed by causal chains of steps, such as sequential actions or a signal sent to<br />

another active object which then executes and eventually sends a signal to the original sender, but actions that are not<br />

causally connected may proceed at different rates.<br />

There is no assumption of synchronous operation of the entire system, nor indeed any assumption that there even<br />

exists a single time across the entire system. There is no assumption of centrality or globality. There is no central<br />

repository, queue, control, timer, arbiter, etc. These are permissible optimizations, but are not be assumed in the fundamental<br />

execution model. We may define an “absolute” time for the convenience of each object so that we may<br />

cause a signal event to be generated at a giventime, but there is no guarantee that 6:00pm for one instance is the same<br />

as 6:00pm for another. However, this does not fundamentally change the constraints on the computation.<br />

This is a relativistic or Einsteinian view of time, and it requires local frames of reference. With local frames of<br />

reference, one cannot know an absolute time, nor an absolute order. A sender may send two events to two receivers<br />

and have the one sent second one arrive first. All that can be guaranteed conceptually is the order of events between<br />

sender and receiver instances. This guarantee allows two state machines to synchronize their behavior.<br />

5.2. Event processing<br />

A send action transmits a signal event to a target active object. In execution, a send actionX creates a signal event<br />

instance that is transmitted to the target active object. The signal event instance comprises a set of argument values<br />

(passed by value, so they may be data values or pointers but not objects) that must conform in type and number to the<br />

parameters specified by the signal event specification.<br />

The transmission may take some finite time, during which both the sender and the receiver may continue to execute.<br />

A received signal event instance is held, in the logical queue, until it can be handled by the target active object.<br />

Active objects may receive signal event instances. There may be a delay between enqueuing an event and handling<br />

it. When all the actions associated with the state machine for an active object are quiescent, an event, if any, is<br />

handled, and the appropiate transition, if any, is fired. The firing of a transition will cause the exit procedure (the set<br />

of actions on exit from a state), the transition procedure, and the entry procedure to execute in sequence. Each procedure<br />

executes the component actions, including executing calls or creating other active or passive objects.<br />

Because each procedure must have a common set of parameters on which it operates, the action semantics<br />

restrict all signal events that leave a state, including histories, to have the same set of parameters. Similarly, all signal<br />

events entering a set must have the same parameters.<br />

stateMachine.fm Version 9 January 7, 2000 7:55 am 27


5 State Machine Execution 5.3 Run to completion<br />

Note. See the submission by Ian Wilkie on this.<br />

5.3. Run to completion<br />

While the procedure is performing actions, it is insensitive to newly-arrived events, which accumulate in the<br />

queue attached to the active object, until all procedures complete.The fact that an active object must complete the<br />

activity triggered by one event before handling another event is called run-to-completion. Run to completion implies<br />

that an active object synchronizes its own subactivity each time it handles an event. If a procedure contains multiple<br />

actions, they must all complete before any of them can receive another event. However, run to completion does not<br />

imply that the chain of activity is atomic. Run to completion merely says that an active object will not process another<br />

event until all actions caused by one event have completed.<br />

Interrupts, such as kills, supersede run to completion. See Chapter XX<br />

Note that a “do activity” must be represented by a “start action” and a “stop action” in a program, to preserve the runto-completion<br />

property.<br />

5.4. Data access conflict<br />

It may happen that two actions may write the same variable, attribute, or link, or one may write and the other read the<br />

same variable, attribute, or link. This is called data access conflict, and the outcome is not determined: either execution<br />

order is possible, or the value read may be total garbage. Conflict may occur at two levels: within a procedure,<br />

when concurrent actions write the same variable, or at the procedure level, when two procedures write to static object<br />

memory.<br />

Conflict amongst the actions in a procedures is managed by the submission in two ways. First, actions communicate<br />

by data flow, and a variable may not be written twice. Second, read and write actions can access tuples of data as<br />

a unit, effectively providing atomic access.<br />

Conflict amongst procedures can only reliably be managed by synchronizing procedures, or by avoiding overlap<br />

in data access sets that are written and read. Models, then, can be designed so that conflict does not occur.<br />

Preventing conflict is a design issue, not a semantics issue. Preventing conflict in the definition of the execution<br />

machinery would cut the heart out of concurrency. Consequently, the action semantics submission does not attempt to<br />

define what happens in case of this type of conflict.<br />

5.5. State Machine Execution Classes<br />

State machine<br />

Each class has a state chart that describes the behavior of a typical instance. The behavior of each instance is<br />

abstracted as a state machine. A state machine serializes the handling of events. It has an event queue into which<br />

events are added asynchronously as they arrive, but the removal of events from the queue and their handling by the<br />

state machine are serial and subject to the control of the state machine. A state machine obeys run-to-completion<br />

semantics: once it starts handling an event, all triggered actions must be completed before another event can be handled.<br />

An state machine can receive an interrupt, which is handled immediately and may result in the premature termination<br />

of ongoing actions.<br />

stateMachine.fm Version 9 January 7, 2000 7:55 am 28


5 State Machine Execution 5.5 State Machine Execution Classes<br />

Constituent associations:<br />

• queued: SignalEventInstanceThe set of event instances received by the active objects but not yet handled. One<br />

signal event instance is designated the current event.<br />

• currentEvent: EventInstance[0..1]An event instance that is being processed by the active object. Once an event is<br />

removed from the queue (under whatever policy) it becomes and remains the current event<br />

while actions triggered by the event are executed. When all actions in an active object<br />

cease activity, the object is said to be quiescent and the current event is discarded in preparation<br />

to handle a new event from the event queue. Run-to-completion means that another<br />

event will not be handled until all activity triggered by a current event has completed.<br />

Note: I left this in though I think the last sentence of the entry above handles it.<br />

SignalEventInstance<br />

An instance of an event set to an active object is abstrated as a Signal Event Instance. <strong>Action</strong>s can instantiate signal<br />

evet instances; instances of other kinds of events (such as time events) are generated by the execution infrastructure in<br />

accordance with specified conditions. The ordered collection of signal event instances is also informally referred to as<br />

the event queue.<br />

Signal events have no inherent identity. They are simply the sum of their values and can therefore be passed by<br />

value and copied freely without loss of information.<br />

The form of time event instances and condition instances needs to be determined as they are a bit vague in <strong>UML</strong><br />

1.3.<br />

Associations<br />

• sender: Send<strong>Action</strong>InstanceThe sending actionX for the signal event instance. At run time, only a single actionX<br />

may generate a sigal event instance<br />

• receiver: StateMachineInstanceThe state machine instance to which the event is sent.<br />

• cariee: Argument A signal event instance comprises several arguments, possibly none, in addition to the target<br />

object identifer.<br />

• spec time: SignalEventSpecEach signal event instance conforms to a specification as given by the Signal Event<br />

Spec.<br />

Others<br />

The remaining classes are:<br />

• SignalEventSpec. At specification time, we specify an event that can be generated to a state chart. Each such<br />

specification is abstracted as a Signal Event Spec. <strong>UML</strong> 1.3 conflates this and the SignalEventInstance.<br />

• Parameter: Defined in <strong>UML</strong>. Question: Is there an association to SignalEvent(Spec)?<br />

• Argument: Defined in <strong>UML</strong>. Association to SignalEventInstance is presumably new.<br />

• Send<strong>Action</strong>Instance. This is a role of actionX, the actionX that is the send action. Unclear whether the role<br />

should be modeled explicitly.<br />

stateMachine.fm Version 9 January 7, 2000 7:55 am 29


5 State Machine Execution 5.5 State Machine Execution Classes<br />

stateMachine.fm Version 9 January 7, 2000 7:55 am 30


III <strong>Action</strong>s<br />

Part III. <strong>Action</strong>s<br />

This part contains descriptions of the various actions that can be included in user models. Related actions are organized<br />

into chapters. For each action, a description in given of its model structure, well-formedness rules on its use<br />

within a model, and its semantics specified by before-after conditions on the state of the execution model.<br />

Arguments of actions<br />

Syntax of action arguments is<br />

name:class<br />

The default attribute multiplicity is 1, otherwise it is shown in brackets after the type name.<br />

<strong>Semantics</strong> specifications<br />

The semantics are given as preconditions and postconditions on the execution values. The values after the action step<br />

are expressed in terms of the values before the step. New values after the step are notated with a prime ('). An<br />

unprimed value represents the previous values. The token performing the step is denoted T and the action being performed<br />

is therefore T.actionPtr. For convenience, we let<br />

A = T.activation<br />

P = T.actionPtr<br />

The phrase “new T”, where T is the name of a class, indicates that an object of the given class is created as part of<br />

the action. Its postcondition values are specified by the semantics.<br />

Multiple sets of preconditions-postconditions-comments may be included in a single actions. The sets are meant<br />

to be applied individually. Each postcondition specification applies to the given precondition.<br />

part-actions.fm Version 9 December 17, 1999 5:04 pm 31


III <strong>Action</strong>s <strong>Semantics</strong> specifications<br />

part-actions.fm Version 9 December 17, 1999 5:04 pm 32


6 <strong>Action</strong> Foundation 6.1 Overview<br />

6.1. Overview<br />

Chapter 6. <strong>Action</strong> Foundation<br />

As previously proposed, local variables provided local, mutable state during the execution of actions within the context<br />

of some overall “procedure.” While this is a typical concept in traditional programming languages, it introduces<br />

additional possibilities for conflict in the presence of internal concurrency between actions in the procedure. That is,<br />

it opens up the possibility of actions concurrently reading and writing the same local variable without synchronization.<br />

To avoid such conflict while retaining local variables requires a complication of the action semantics and potentially<br />

an undesired reduction in allowed concurrency. On the other hand, the possibility for conflict comes without<br />

much real gain in power. While local variables may be traditional, there are data-flow and single-assignment languages<br />

that do quite well without them. And, in fact, such languages can deal much more simply with fine-grained<br />

concurrency.<br />

So, we can eliminate the problems with local variables by eliminating local variables all together. In this case,<br />

actions can only obtain values from other actions via data-flow connections (at least without resorting to “external”<br />

state-modifying side effects, such as writing then reading an object attribute). The result is an approach to action composition<br />

that allows the maximum amount of internal concurrency without introducing unnecessary potential for conflict.<br />

In this note, we attempt to address the building of an action metamodel foundation based on this approach. Since<br />

the main area of difficulty with the approach is dealing with control constructs, we also address such “composite”<br />

actions.<br />

6.2. Summary<br />

An action is the basic unit of behavior. In general, when executed, an action takes some input values, performs some<br />

processing and produces some set of output values. This may be viewed schematically as follows. (Note that the<br />

graphical notation used here is intended to be illustrative and not a proposal for an actual surface language.)<br />

input<br />

pins<br />

action<br />

output<br />

pins<br />

Figure 4. <strong>Action</strong> and pins<br />

Input pins are the connection points for delivering the input values to actions. Output pins are the connection<br />

points for obtaining the output values from actions. The types and multiplicities of the input and output pins of an<br />

action are constrained by the form of the action. For example, an action that reads a certain attribute has an output pin<br />

with the type and multiplicity of that attribute, while an action that writes to an attribute has an input pin with the type<br />

and multiplicity of that attribute. An action that calls an operation has input and output pins with types and multiplicities<br />

corresponding to the input and output parameters of the operation.<br />

Note. The types of the input and output pins of an action form the input and output “signature” of the action.<br />

The signature is modeled by derivation from the types of the input and output pins; it is not modeled explicitly.<br />

Some actions impose constraints on the types of some of their pins.<br />

actionFoundation.fm Version 9 December 17, 1999 5:04 pm 33


6 <strong>Action</strong> Foundation 6.2 Summary<br />

A data flow from an output pin to an input pin indicates that an output value of one action is used as an input<br />

value of another action. This is shown schematically below.<br />

action<br />

Figure 5. Data flow<br />

Note that a single output pin can be connected to multiple (zero or more) input pins. However, each input pin can<br />

have at most one connection. Thus, inputs pins are effectively “single assignment” data holders—once they receive a<br />

value, this value does not change. In other words, normal data-flow connections allow “fan out” (as shown above), but<br />

not “fan in.”<br />

The input pin that is the destination of a data flow must conform to the output pin that is the source of the flow.<br />

Conformance means that the type of the output pin is the same as or a descendant of the type of the input pin, and all<br />

cardinalities allowed by the multiplicity of the output pin are allowed by the multiplicity of the input pin. For example,<br />

if the type of the output pin is money, and the type of the input pin is real, and money is a descendant of real, then<br />

the types conform.<br />

A control flow indicates a predecessor action that must complete all execution before a successor action can<br />

begin to execute. Control flows permit normal imperative programming, and make it possible to sequence actions<br />

explicitly, particularly when the actions have memory-modifying side effects (e.g., writing or reading a value of an<br />

attribute). All these requirements can be captured using control flows.<br />

Two such control flows are shown schematically below. Both predecessor actions (A and B) must be completed<br />

before the successor action (C) can execute.<br />

action A<br />

data flow<br />

Figure 6. Control flow<br />

action<br />

action<br />

predecessors action C successor<br />

action B<br />

control flow<br />

A data flow implies a control dependency in the sense that an executing action cannot consume an input value<br />

during execution until it has been produced by the source action. Control sequencing is implicit between actions connected<br />

by data flows; it is unnecessary to include explicit control flows between such actions. Explicit control flows<br />

must not violate the sequencing implied by data flows.<br />

A primitive action is one that cannot be decomposed into other actions. Primitive actions include purely mathematical<br />

functions, such as arithmetic and string functions, actions that work on object memory, such as read actions<br />

and write actions, and actions related to object interaction, such as call actions and send actions. Each kind of primi-<br />

actionFoundation.fm Version 9 December 17, 1999 5:04 pm 34


6 <strong>Action</strong> Foundation 6.2 Summary<br />

tive action has a form that specifically defines sets of input and output pins. The details of the various kinds of primitive<br />

actions are not considered further in this note.<br />

Primitive actions may be composed into composite actions, which may in turn be themselves parts of larger composites.<br />

Depending on the form of the composite, data flows may cross the boundary of a composite and connect to<br />

input and output pins of actions within the composite. (There are constraints imposed by some composites. See the<br />

description of each one.) Such pins may be owned by the composite or by actions (including other composite actions)<br />

nested within it. Pins directly or indirectly within a composite action that may be connected to flows crossing the<br />

boundary of the composite are said to be available inputs and available outputs of the composite. For example, consider<br />

the composite shown schematically below.<br />

composite action<br />

m<br />

n<br />

action<br />

p<br />

action<br />

action<br />

Figure 7. Data flows across composite action boundary<br />

The pins labeled m, n and q are available inputs for the composite, while pin r is not (since it is already connected<br />

within the composite). An input pin is an available input only if it is not already connected within the composite, and<br />

the connection rules permit its connection outside the composite. Pins x, y and z are available outputs, and so is pin p<br />

(since any output may be connected more than once). An output pin is an available output if the connection rules permit<br />

its connection outside the composite. The description of each kind of composite defines the connection rules for<br />

available inputs and outputs. Thus, if we “zoom out” to a higher-level view gives an effective external view such as<br />

shown below.<br />

available<br />

inputs<br />

Figure 8. Available inputs and outputs of composite action<br />

While in this view the available input and output pins are shown as inputs and outputs of the composite action, it<br />

is important to remember that the composite action in this case does not actually own those pins, actions inside the<br />

composite do. Drawing the available inputs and outputs of a composite action, as above, is simply an illustrative convenience.<br />

However, some composite actions (conditionals and loops) may actually also have pins of their own, which<br />

are included in their sets of available inputs and/or outputs. This is discussed in detail in the following section on<br />

composite actions. For generality, primitive actions may be considered to have available inputs and outputs, too,<br />

which are the same as the input and output pins that they own.<br />

At the highest level of composition, an action can provide the behavioral specification for a procedure. A procedure<br />

can be the body of a method, or it may specify the behavior executed on exit from a state, on a transition or on<br />

actionFoundation.fm Version 9 December 17, 1999 5:04 pm 35<br />

q<br />

r<br />

q<br />

p<br />

m composite<br />

x<br />

available<br />

y<br />

n action<br />

outputs<br />

z<br />

x<br />

y<br />

z


6 <strong>Action</strong> Foundation 6.2 Summary<br />

entry to a state. The inputs of the action take their values from the arguments of the procedure (corresponding to the<br />

input parameters) and the outputs of the action provide the results of the procedure (corresponding to the output<br />

parameters). Effectively, then, we treat the body of a method, and the behavior associated with exit from, transition to,<br />

or entry to a state each as a procedure with arguments and results. (Note that methods and transitions triggered by call<br />

events may have results; other transitions, as well as entry and exit procedures, do not have results.)<br />

So that the arguments can be attached to the available inputs of the action using normal data flows, the arguments<br />

are represented as output pins within the procedure (they supply values to the action). Similarly, the results are represented<br />

as input pins within the procedure (they use values produced by action). This is shown schematically below.<br />

procedure (a,b): x,y<br />

a<br />

x<br />

arguments action<br />

results<br />

b<br />

y<br />

Figure 9. Procedure with pins and action<br />

Note that, to be well formed, the ordered list of arguments and results of the procedure must match the types and<br />

multiplicities of the corresponding (by order) parameters of the method or event. (The in and in-out parameters must<br />

conform to the argument pins, and the result pins must conform to the in-out, out and return parameters.) However,<br />

these are well-formedness rules for a method or event-triggered transition that are not considered further here.<br />

Argument pins are output pins, and therefore each one may be connected to zero or more available inputs of the<br />

action. Result pins are input pins, and therefore each one must be connected to exactly one available output of the<br />

action. The data flow connections must follow the normal connection rules for input and output pins.<br />

Note. The previous metamodel had a “procedure action” as a kind of group action. However, on reflection, it<br />

seems better to not have a procedure be a kind of action. A procedure is intended to be solely a top-level construct,<br />

and so it should not be included in composite actions like other actions can be.<br />

actionFoundation.fm Version 9 December 17, 1999 5:04 pm 36


6 <strong>Action</strong> Foundation 6.3 Foundation Classes<br />

The above foundational concepts for actions are reflected in the following metamodel.<br />

ControlFlow<br />

*<br />

*<br />

+antecedant<br />

+predecessor 1<br />

Primitive<strong>Action</strong><br />

+consequent<br />

+successor<br />

1<br />

<strong>Action</strong><br />

+action 1<br />

Note. It might be desirable to make the association between <strong>Action</strong> and Procedure bidirectional. However, in<br />

this case, consistency would argue that all possible composition as associations of <strong>Action</strong> should be bidirectional<br />

(i.e., compositions with Group<strong>Action</strong> and Clause in the next section). But this would add a lot of<br />

knowledge to the specification of <strong>Action</strong> of its composite-action subclasses, which might not be particularly<br />

desirable. There is no inherent reason why an action need know that it is a top-level action within a procedure,<br />

therefore the association is shown as directed.<br />

6.3. Foundation Classes<br />

*<br />

*<br />

ModelElement<br />

Classifier +type<br />

Pin<br />

1 * multiplicity : Multiplicity<br />

+action<br />

+outputPin<br />

0..1<br />

+action<br />

{ordered} * OutputPin 1<br />

+source<br />

0..1<br />

{ordered}<br />

+inputPin *<br />

*<br />

{ordered}<br />

+argument<br />

+flow *<br />

+/availableInput<br />

*<br />

*<br />

{ordered}<br />

InputPin<br />

+/availableOutput *<br />

+result<br />

+destination<br />

Figure 10. <strong>Action</strong> foundation metamodel<br />

+procedure<br />

DataFlow<br />

Procedure<br />

<strong>Action</strong><br />

An action is the fundamental unit of behavior specification. In general, an action takes a set of inputs and converts<br />

them into a set of outputs, though either or both sets may be empty. (If both inputs and outputs are missing, the action<br />

must perform some kind of fixed, nonparameterized side effect on the system state, but it is possible to think of such<br />

actions.) <strong>Action</strong>s may access or modify accessible, mutable objects. (Note that, by definition, changes to mutable<br />

objects are side-effects on the memory of the object, not data flow. However, references to objects to read or write and<br />

values to write are passed as data flow inputs to read or write actions, and data values read from objects are passed to<br />

subsequent actions as data flows. The result of a write action is not a new object pointer. In this case, the object iden-<br />

actionFoundation.fm Version 9 December 17, 1999 5:04 pm 37<br />

1<br />

+flow<br />

0..1<br />

0..1<br />

0..1<br />

+procedure<br />

0..1


6 <strong>Action</strong> Foundation 6.3 Foundation Classes<br />

tity has not changed. Write actions have their effects by side effects on the system state.) Composite actions may<br />

include data-transformation actions as well as object-access actions.<br />

An action may have a set of incoming data flows as well as a set of explicit control flow dependencies to predecessor<br />

actions. An action will not begin execution until all of its input values (if any) have been produced by preceding<br />

actions and all predecessor actions have completed.The completion of the execution of an action may enable the<br />

execution of a set of successor actions and actions that take their inputs from the outputs of the action. <strong>Action</strong>s come<br />

in various kinds, each of which has its own formation rules. An action must be one of those kinds.<br />

Associations<br />

• antecedent The set of control flows that must be enabled before this action can execute.<br />

• availableInput (derived) The set of all input pins available to be the destinations of data flows from outside<br />

the action. This implies that they are not connected by data flows within the action.<br />

The derivation rule is defined for each kind of action.<br />

• availableOutput (derived) The set of all output pins available to be the sources of data flows out of the<br />

action. The derivation rule is defined for each kind of action.<br />

• consequent The set of control flows that are enabled when this action finishes executing.<br />

• inputPin The ordered set of input pins owned by the action, which act as connection points for providing<br />

values consumed by the action<br />

• outputPin The ordered set of output pins owned by the action, which act as connection points for<br />

obtaining values generated by the action.<br />

Well-formedness rules<br />

[1] There must be no cycles in the graph of actions and flows, where a cycle is defined as a path that begins and ends<br />

at the same action and a path is constructed from directed edges between actions, with control flows traversed<br />

from predecessor action to successor action and data flows traversed from the action of the source pin to the<br />

action of the destination pin. A control flow from or to a group action is treated as being a set of control flows<br />

from or to each action within the group action.<br />

Note. This is a necessary but not sufficient condition to prevent ill-formed control cycles. There are additional<br />

conditions related to conditional and loop actions that are handled below as well-formedness rules for<br />

those kinds of actions.<br />

ControlFlow<br />

A control flow represents a sequencing dependency between two actions. The successor action of the flow may not<br />

execute until the predecessor action has completed execution.<br />

Associations<br />

• predecessor The action that must finish executing before the successor can execute.<br />

• successor The action that cannot execute until the predecessor completes execution.<br />

DataFlow<br />

A data flow is a carrier of values from a source output pin to a destination input pin. When a value is generated on the<br />

source pin, it is copied to the destination pin. The source pin must therefore conform in type and multiplicity to the<br />

destination pin<br />

actionFoundation.fm Version 9 December 17, 1999 5:04 pm 38


6 <strong>Action</strong> Foundation 6.3 Foundation Classes<br />

Associations<br />

• destination The input pin that receives the data carried by the flow.<br />

• source The output pin that provides the data carried by the flow.<br />

Well-formedness rules<br />

[1] The type of the source pin must be the same as or a descendant of the type of the destination pin.<br />

[2] All cardinalities allowed by the multiplicity of the source pin must be allowed by the multiplicity of the destination<br />

pin.<br />

InputPin<br />

An input pin is a pin that represents input values to be consumed by an action. An input pin may be the destination for<br />

at most one data flow. In this case, the input pin receives its values from the source output pin of the data flow.<br />

Associations<br />

• action The action that owns the pin as an input (not used with procedures)<br />

• flow The data flow for which this input pin is the destination.<br />

• procedure The procedure that owns the pin as a result (not used with actions).<br />

Well-formedness rules<br />

[1] An input pin must be owned by either an action or a procedure.<br />

OutputPin<br />

An output pin is a pin that represents output values generated by an action. A single output pin may have several dataflow<br />

connections to several input pins. In this case, the output pin provides a copy of its value to each of the associated<br />

input pins.<br />

Associations<br />

• action The action that owns the pin as an output.<br />

• flow The data flow for which this output pin is the source.<br />

• loop The loop action that owns the pin as a loop variable (see the discussion under Composite<br />

<strong>Action</strong>s).<br />

• procedure The procedure that owns the pin as an argument.<br />

Well-formedness rules<br />

[1] An output pin must be owned by either an action or a procedure.<br />

Pin<br />

A pin is a connection point for delivering input values to or obtaining output values from an action. Any values passing<br />

through the pin must conform to the type of the pin and have cardinalities allowed by the multiplicity of the pin.<br />

Pin is completely specialized into input and output pins.<br />

actionFoundation.fm Version 9 December 17, 1999 5:04 pm 39


6 <strong>Action</strong> Foundation 6.3 Foundation Classes<br />

Attributes<br />

• multiplicity A specification of the number of values a pin may hold at any one time.<br />

Associations<br />

• type A classifier specifying the allowed classifiers of values passing through the pin. The actual<br />

classifier of a value must conform to the type specification of the pin.<br />

Primitive<strong>Action</strong><br />

A primitive action is one that does not contain any nested actions, so all available inputs and outputs of the action are<br />

pins directly owned by the action. Primitive<strong>Action</strong> describes the common properties of all the various kinds of primitive<br />

actions.<br />

Well-formedness rules<br />

[1] The available inputs of a primitive action are the input pins of the action.<br />

[2] The available outputs of a primitive action are the output pins of the action.<br />

Note. Primitive<strong>Action</strong> is really only defined as a convenience to provide a common definition of these wellformedness<br />

rules for all kinds of primitive actions.<br />

Procedure<br />

A procedure may act as the body of a method or the reaction to an event. The behavior of the procedure is specified<br />

using an action. The procedure has an ordered list of arguments, represented as output pins, that may be connected as<br />

sources to the available inputs of the body action. It also has an ordered list of results, represented as input pins, which<br />

must be connected as destinations to the available outputs of the body action.<br />

Associations<br />

• action The action that provides the behavioral specification of the procedure.<br />

• argument The ordered set of output pins representing procedure arguments.<br />

• result The ordered set of input pins representing procedure results.<br />

Well-formedness rules<br />

[1] All available inputs of the action of a procedure must be the destinations of flows, the sources of which are arguments<br />

of the procedure.<br />

[2] All results of a procedure must be the destination of flows, the sources of which are available outputs of the<br />

action of the procedure.<br />

actionFoundation.fm Version 9 December 17, 1999 5:04 pm 40


7 Composite <strong>Action</strong>s 7.1 Group <strong>Action</strong><br />

Chapter 7. Composite <strong>Action</strong>s<br />

Composite actions are recursive structures that permit more complex actions to be composed from simpler action.<br />

Depending on its structure, a composite action can contain other composite actions as well as primitive actions. Ultimately<br />

the leaves of the action tree are primitive actions.<br />

7.1. Group <strong>Action</strong><br />

The simplest form of composite action is the group action. A group action simply composes a set of actions into a single<br />

higher-level unit. These actions may be interconnected within the group.<br />

A group action does not own any pins of its own. Data flows may “cross the boundary” of a group action to connect<br />

to input an output pins of actions within the group. In effect, the boundary of the group action is “porous”, allowing<br />

input values to flow into the group and output values to flow out. This approach to grouping is intended to focus<br />

on convenience in organizing a computation rather than encapsulation of decomposition.<br />

When can define this more precisely using the concept of available inputs and available outputs introduced in the<br />

previous section. Any available inputs of actions within the group that are not connected within the group are available<br />

inputs of the group as a whole. All the available output actions within the group are available outputs of the group<br />

as a whole (since there is no restriction on the number of data-flow connections an output pin may have).<br />

This is shown schematically below.<br />

A<br />

group action<br />

m<br />

n<br />

action E<br />

B<br />

p<br />

C D<br />

action F<br />

action G<br />

Figure 11. Group action and its flows<br />

Group actions can be predecessors and successors in control flows, so they provide the ability to synchronize on<br />

the execution of groups of actions, as shown in the diagram above. A control flow whose destination is a group action<br />

requires that the predecessor must complete before any action within the group action may begin. A control flow<br />

whose source is a group action requires that all actions within the group action must complete before the successor<br />

may begin.<br />

Control-flow connections may also cross the boundary of a group action, allowing synchronization on individual<br />

actions within the group. Other actions in the same group action are not affected by such a direct control flow connection<br />

into the group action.<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 41<br />

q<br />

r<br />

x<br />

y<br />

z


7 Composite <strong>Action</strong>s 7.1 Group <strong>Action</strong><br />

For instance, in the example shown above, predecessor action A must complete before any of the actions inside<br />

the group—E, F, and G—can execute. All of the interior actions E, F, and G must complete before exterior action D<br />

can execute. In addition, exterior action B must complete before interior action G can execute, but interior actions E<br />

and F are unaffected by exterior action B. <strong>Action</strong> E must also wait for the actions that produce its input values m and<br />

n. <strong>Action</strong> F must also wait for interior action E to complete, because it uses data produced by E. <strong>Action</strong> F is concurrent<br />

with actions E and G. It must wait for its input value p produced by an exterior action. Exterior action C must<br />

wait for interior action E to complete, but it need not wait for actions F and G. Any actions that use values x and y<br />

must wait for action F. Any actions that use value z must wait for action G.<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 42


7 Composite <strong>Action</strong>s 7.2 Conditional <strong>Action</strong><br />

7.2. Conditional <strong>Action</strong><br />

The other forms of composite action provide for control structuring. A conditional action provides for the conditional<br />

execution of contained actions depending on the result of test actions. The structure of a conditional action is shown<br />

schematically below.<br />

conditional action<br />

clause<br />

test<br />

test<br />

test<br />

Figure 12. Conditional action and pins<br />

As shown above, a conditional action contains a set of clauses, each of which consists of a test action and a body<br />

action. The test action must have an output of type Boolean that is used to control whether or not the body action is<br />

executed. The body action can be executed only if the test output has the value “true”. This implicit conversion of a<br />

data flow to a control flow is shown above as a small diamond. The implicit control flow is not actually explicitly<br />

included in a model. (Note that, per the discussion on group actions above, if any the test or body actions are group<br />

actions, then the input and output pins diagrammed above for these actions are really available input and output pins<br />

of the group actions.)<br />

Note. We have chosen here to have tests return normal Boolean data outputs, which are then implicitly converted<br />

to control flows. Actually, only a very primitive concept of Boolean is necessary with the distinguished<br />

data values “true” and “false”)<br />

In addition to the implicit “success” control flow (enabled when the test results in “true”) that triggers the body of<br />

a clause, there is also implicitly a complementary “failure” control flow (enabled when the test completes execution<br />

but does not result in “true”). This is shown above as a second control flow arrow from the little diamonds. The test<br />

action of one clause may be the destination of the implicit “failure” control flows of the test actions of other clauses,<br />

meaning that it can only execute if the test actions of the other clauses all fail. This is useful, for example, if a predecessor<br />

test is necessary to ensure the validity of the successor test (such as first testing for null pointers or empty containers).<br />

In the absence of such control-flow constraints, test actions are executed concurrently. Since failure control-flow<br />

connections are thus optional, they must be included explicitly in the metamodel. They are actually captured as control<br />

flows between the tests themselves, though unlike other control flows they only fire if the test source test completes<br />

execution and fails. (These are not actually normal control flows, and their form within the conditional is<br />

highly constrained.)<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 43<br />

body<br />

body<br />

body<br />

conditional<br />

output<br />

pins


7 Composite <strong>Action</strong>s 7.2 Conditional <strong>Action</strong><br />

In any execution of a conditional action, exactly one body action is executed. If the results of the test evaluation<br />

imply that more than one body action is triggered for execution, then exactly one action is selected for execution, but<br />

it is unspecified which one. At least one test action must always evaluate to true or the conditional action is ill formed.<br />

(Note that there is no guarantee that the execution environment will produce a “fair” or random outcome in its selection<br />

of an action to execute—it might always pick the same outcome, but then it might not. The modeler, though, has<br />

no way to predict this and must not assume any particular result or pattern.)<br />

If the tests are not otherwise guaranteed to be exhaustive, then this can be ensured by providing a default action<br />

with a test of “true” that is a successor of all other tests (as shown in the diagram above). Such a default clause is not<br />

required in all cases, however, because this would impose an unnecessary burden on those models in which all of the<br />

choices can be exhaustively enumerated.<br />

Indeed, in many cases the tests in a conditional will be both exhaustive and mutually exclusive by design. This<br />

case is common and important enough that the conditional action can be explicitly tagged as being “determinate.” In<br />

this case, exactly one concurrent test action must evaluate to true.<br />

Determinism is an assertion by the designer—if it is not correct, the model is ill formed. It can be achieved either<br />

by complete, explicit sequencing of the test actions or through the designer’s knowledge that tests that are not<br />

sequenced are mutually exclusive. Note that the latter case does not imply a need for the run-time system to test that<br />

the other tests do indeed evaluate to false—the developer has the responsibility to guarantee mutual exclusion. (If the<br />

tests are totally sequenced explicitly, then mutual exclusion is guaranteed in any case, so the flag is really needed only<br />

in case the tests are not totally sequenced.)<br />

The available inputs of all test and body actions must be connected to output pins outside the conditional action.<br />

Thus the available inputs of the entire set of test and body actions are the available inputs of the conditional action as<br />

a whole. The conditional action as a whole owns an ordered set of output pins. Each clause must identify as its outputs<br />

an ordered list of available outputs of its body action. This list must be of the same size as the list of outputs of<br />

the conditional. Further, the each output pin of each clause must conform in type and multiplicity to the corresponding<br />

output pin of the conditional. Whichever (single) clause of the conditional action has its body executed, the values<br />

of the outputs of that clause are implicitly copied to the conditional output pins.<br />

Conditional actions provide the only points of effective “fan in” of data flow. This fan in within a conditional<br />

action does not violate the “single assignment” principle, however, since only one of the body actions can execute<br />

during any execution of the conditional action, so the each conditional output pin will receive only one value. Also,<br />

since exactly one body action must execute, each conditional output pin will always receive a value.<br />

The available outputs of a body action may not be directly connected to input pins outside the body action. The<br />

available outputs of test actions may not participate in data flows at all.<br />

Note. In principle, available outputs of a test could be connected to available inputs of the corresponding<br />

body, but it seems simpler to keep the test and body actions separate except for their implicit control link.<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 44


7 Composite <strong>Action</strong>s 7.3 Loop <strong>Action</strong><br />

7.3. Loop <strong>Action</strong><br />

The final kind of composite action is the loop action. The loop action provides for repeated execution of a contained<br />

action so long as a test action results in an appropriate value. The structure of a loop action is shown schematically<br />

below.<br />

conditional action<br />

clause<br />

test body<br />

fixed value (during loop)<br />

loop<br />

variables<br />

Figure 13. Loop and pins<br />

loop input pins<br />

loop<br />

output<br />

pins<br />

As shown above, the loop action contains a single clause with a test action and a body action. The body action is<br />

executed repeatedly as long as the test action outputs “true”. The body action operates on a set of “loop variables,”<br />

which are represented as an ordered set of output pins defined within the loop action.<br />

As output pins, the loop variables may be connected to available inputs of the test and body actions. They provide<br />

the “old values” or “current values” of the loop variables during a loop iteration. The clause outputs, which must conform<br />

to the types and multiplicities of corresponding loop variables, provide the “new values” or “next values” of the<br />

loop variables at the end of an iteration. The values of the clause outputs are implicitly copied to the loop-variable<br />

pins, to become the “old values” for the next iteration.<br />

Before the first iteration, the loop variables are initialized with the values from a corresponding ordered set of<br />

loop input pins, which must conform in type and multiplicity to the loop variables. The test is performed after the initial<br />

values of the loop are copied to the loop variables, before the body is first executed. If the test outputs true, then<br />

the body is executed. Otherwise the loop terminates without executing the body at all and the values of the loop variables<br />

are copied to the corresponding loop output pins. The loop variables must conform in type and multiplicity to<br />

the loop output pins.<br />

After each execution of the body, the test is executed again using the new values of the loop variables (i.e., the<br />

values produced by the previous execution of the body). If the output value of the test is true, the body is executed<br />

again. Otherwise, the values of the loop variables are copied to corresponding loop output pins, and the execution of<br />

the loop is complete.<br />

Note that the loop variables are not explicitly “reassigned” in the body action. Instead, the input and output pins<br />

for the body action hold the “old values” and the “new values” of the loop variables during a single iteration. This preserves<br />

the single-assignment principle, at least as far as the loop body action is concerned.<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 45


7 Composite <strong>Action</strong>s 7.4 Concurrent Collection <strong>Action</strong>s<br />

7.4. Concurrent Collection <strong>Action</strong>s<br />

The map and reduce actions invoke an action concurrently on the elements of a collection. In the map action, an<br />

action is applied concurrently to each of the elements of the collection. Each input value must be a collection; all the<br />

collections must have the same shape (number of elements and class of element). If the action has output values, they<br />

are assembled into a new collection of the same shape as the input collection.<br />

The reduce action invokes an associative action with two input pins and one output pin, all of the same type. This<br />

action accepts as input a collection whose elements are of the type accepted by the associative action. The action is<br />

repeatedly applied to adjoining pairs of elements with the result replacing the pair of elements. When a single value<br />

remains, the reduce action produces the single value as its output. The result of executing the reduce action does not<br />

depend on the order in which pairs of values are evaluated (assuming there are no side effects). Common rank-reduction<br />

functions such as sum, product, maximum value, Boolean and and or, and many others can be expressed as<br />

reduce actions.<br />

7.5. Composite Classes<br />

The above structures for composite actions are formalized in the following metamodel.<br />

+subaction<br />

0..1<br />

*<br />

<strong>Action</strong><br />

1<br />

Group<strong>Action</strong><br />

+test<br />

1 0..1<br />

+body<br />

+testOutput 1<br />

0..1<br />

OutputPin<br />

0..1<br />

Clause<br />

Conditional<strong>Action</strong><br />

isDeterminate : Boolean<br />

Figure 14. Composite actions metamodel<br />

Clause<br />

A clause is a part of a conditional or loop action. A clause contains a test action and a body action. The execution of<br />

the body action is conditional on the execution of a test action and its producing a “true” value. The clause distinguishes<br />

one available output of the test action, which must have type Boolean; the body action is only executed if this<br />

output has the value “true”. (Additionally, for a conditional, only one clause body is executed even if more than one of<br />

their tests is true.) The outputs of the clause are an ordered subset of the available outputs of the body action.<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 46<br />

*<br />

*<br />

1..*<br />

+output<br />

{ordered}<br />

+clause<br />

0..1<br />

+loopVariable<br />

* {ordered}<br />

+clause<br />

1<br />

Loop<strong>Action</strong><br />

0..1<br />

0..1<br />

+loop


7 Composite <strong>Action</strong>s 7.5 Composite Classes<br />

During the execution of an enclosing conditional action, a test action may not execute unless all of its predecessor<br />

test actions (if any) have executed and produced “false” values. A test action may not participate in any explicit<br />

control flows except control flows among test actions contained in the same conditional. A body action may not participate<br />

in any explicit control flows.<br />

Associations<br />

• test The action whose Boolean result must be true for execution of the body action to proceed.<br />

• testOutput The available output pin of the test action whose value is the test result. It is this output<br />

that is converted to the control flow that manages which body to execute.<br />

• body The action whose execution is contingent on the result of the test action.<br />

• output The ordered set of available outputs of the body that are considered to be results of the<br />

clause.<br />

Well-formedness rules<br />

[1] None of flows attached to the available outputs of the test action of a clause may have destinations outside the test<br />

action.<br />

[2] The testOutput of a clause must be an available output of the test action.<br />

[3] The testOutput pin must conform to type Boolean and multiplicity 1..1.<br />

[4] None of the actions within the test action of a clause (if any) may have control-flow connections with actions outside<br />

the test action.<br />

[5] None of the actions within the body action of a clause (if any) may have control-flow connections with actions<br />

outside the body action.<br />

[6] The body action of a clause may not participate in control flows.<br />

[7] An output of a clause must be an available output of the body of the clause.<br />

Conditional<strong>Action</strong><br />

A conditional action consists of a set of one or more clauses, exactly one of whose bodies is executed during any execution<br />

of the conditional action. If more than one clause has a test that outputs “true”, then exactly one of the corresponding<br />

body actions is selected for execution, but it is unspecified which one. (However, if the conditional action is<br />

an “determinate,” then exactly one concurrent clause test must return true.) Each clause must have an ordered list of<br />

output pins that conform to the ordered list of output pins of the conditional. The only available outputs of the conditional<br />

action as a whole are the output pins owned by the conditional action directly.<br />

Attributes<br />

• isDeterminate If true, then whenever the conditional action is executed, exactly one test action must<br />

result in “true”. (This is an assertion, not an executable property. If the assertion is not<br />

true, the model is ill formed.)<br />

Associations<br />

• clause The set of clauses contained in the conditional action.<br />

Well-formedness rules<br />

[1] Each clause of a conditional action must have a number of outputs equal to the number of output pins of the conditional<br />

action. Each output of a clause must conform in type and multiplicity to the corresponding output of the<br />

conditional.<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 47


7 Composite <strong>Action</strong>s 7.5 Composite Classes<br />

[2] No data flow attached to an available output of the test or body actions of a clause of a conditional action may<br />

have a destination outside that action.<br />

[3] The test action of a clause of a conditional action may not participate in control flows other than with the test<br />

actions of other clauses in the conditional action.<br />

[4] A conditional action owns no input pins.<br />

[5] The available inputs of a conditional action are the union of the available inputs of the test actions and body<br />

actions of all the clauses of the conditional action.<br />

[6] The available outputs of a conditional action are the output pins of the conditional action.<br />

[7] There may be no path from an output pin of a conditional action to any action within the conditional action<br />

(where a path is defined as in rule [1] for <strong>Action</strong>).<br />

Group<strong>Action</strong><br />

Output: none<br />

Parameters: clause:Clause[0..*]<br />

Consists of a set of clauses, each of which has a condition and a body action. The condition is itself an action that<br />

yields a Boolean value. Evaluation of the condition must not cause side effects in the system state.<br />

The referenced clauses may have TestOrder links (predecessor-successor) among themselves to specify the<br />

sequencing constraints among the tests of the guard conditions. If these are arranged sequentially, the testing is totally<br />

deterministic. Otherwise the outcome may be nondeterministic.<br />

The condition values are evaluated in the order specified by the test order; the body of exactly one clause whose<br />

condition evaluates to true is executed, unless no conditions are true, in which case no statement is executed. A clause<br />

body will not be executed unless the guard conditions of all of its predecessors test false. If there is no constraint<br />

among two clauses and both of their guard conditions test true, the choice of which body to execute is nondeterministic,<br />

but only one will be executed in any case whatsoever.<br />

If there are no sequencing constraints among clauses, there is a nondeterministic choice among the clauses whose<br />

guard conditions test true; this is similar to a set of state transitions, only one of which is triggered. If the clauses are<br />

arranged as a list by a chain of constraints, the construct represents an if..elseif...elseif... chain. A literal true condition<br />

represents an else clause. If all the conditions are true but there are no constraints, the construct represents a nondeterministic<br />

branch. By the proper choice of guard conditions, a case statement can be represented.<br />

<strong>Semantics</strong><br />

T: ExclusiveSetToken; P->type = ExclusiveSet<br />

Comment: must keep track of the statements whose guards have been tested because of precedence constraints, only<br />

enable one action even if multiple guards are true, the choice is nondeterministic<br />

Precondition: T.status = ready<br />

Postcondition: T.status' = testing<br />

T.subtoken' = {for each C:Clause in P.clause | new U:ClauseToken where U.actionPtr = C and U.status = unready<br />

}<br />

Comment: start the testing, create tokens to keep track of what has been tested<br />

Precondition: T.status = testing; (there exists U in T.subtoken | U.status = unready and<br />

(for each Q in U.actionPtr.predecessor there exists Y in T.subtoken | Y.actionPtr = Q and Y.status = failed and<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 48


7 Composite <strong>Action</strong>s 7.5 Composite Classes<br />

(there does not exist W in T.subtoken | W.status = testing) and<br />

U.actionPtr.guard is not empty)<br />

Postcondition: U.status' = testing; new V: ConditionToken; U.test = V; V.actionPtr = U.actionPtr.guard; V.status =<br />

ready<br />

Comment: If no test is outstanding, find a statement whose predecessors have failed and test it. The assumption is that<br />

the setup step is atomic, at least within the action set, otherwise two concurrent statements could be enabled<br />

simultaneously, the test for an existing execution notwithstanding. This step introduces nondeterminism. The<br />

tests themselves are not concurrent, although they could be made so, but that would require killing uncompleted<br />

tests.<br />

Precondition: T.status = testing; (there exists U in T.subtoken | U.status = unready and<br />

(for each Q in U.actionPtr.predecessor there exists Y in T.subtoken | Y.actionPtr = Q and Y.status = failed and<br />

(there does not exist W in T.subtoken | W.status = testing) and<br />

U.actionPtr.guard is empty)<br />

Postcondition: T.status' = executing; U.status' = executing; new W: Token; T.body' = W; W.actionPtr =<br />

U.actionPtr.body; W.status' = ready<br />

Comment: If no test is outstanding, find a statement whose predecessors have failed and and whose guard condition is<br />

absent (and therefore true) and execute its body.<br />

Precondition: T.status = testing and (there exists U in T.subtoken | U.status = testing and<br />

V = U.test and V.status =passed)<br />

Postcondition: T.status' = executing; U.status' = executing; destroy V'; new W: Token; T.body' = W; W.actionPtr =<br />

U.actionPtr.body; W.status' = ready<br />

Comment: If a test succeeds, then execute the corresponding body and stop testing<br />

Precondition: T.status = testing and (there exists U in T.subtoken | U.status = testing and<br />

V = U.subtoken and V.status =failed)<br />

Postcondition: destroy V'; U.status' = failed<br />

Comment: if a guard fails, mark the clause as failed<br />

Precondition: T.status = testing and (for each U in T.subtoken) U.status = failed<br />

Postcondition: T.status' = complete; destroy T.subtoken' and contents<br />

Comment: if all the guards fail, then don’t execute anything, the statement is complete<br />

Precondition: T.status = executing and (there exists U in T.subtoken) U.status = executing and U.subtoken.status =<br />

complete<br />

Postcondition: T.status' = complete; destroy T.subtoken' and all contents, including U'<br />

Comment: when the triggered action is complete, then the statement is complete<br />

Comment: An if-elseif chain is just a special case of an exclusive set with predecessors arranged linearly.<br />

Group<strong>Action</strong><br />

A group action represents a simple composition of a set of subactions. A group action does not own any pins of its<br />

own, but data-flow connections may (generally) be made from actions outside the group to pins owned by actions<br />

within the group action. The group action as a whole may participate in control flows and actions within the group<br />

action may also participate in control flows with actions outside the group action. There is an implicit control flow<br />

from the group action to each action within it; this is important only if there is a control flow to the group action. Sim-<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 49


7 Composite <strong>Action</strong>s 7.5 Composite Classes<br />

ilarly, there is an implicit control flow from each action in the group action to the group action; this is important only<br />

if there is a control flow from the group action.<br />

Associations<br />

• subaction The set of actions contained in the group.<br />

Well-formedness rules<br />

[1] A group action does not own any pins.<br />

[2] The set of available inputs of a group action is the union of the available inputs of all the subactions of the group<br />

action not connected within the group action to an output of a subaction of the group action.<br />

[3] The set of available outputs of a group action is the union of the available outputs of all the subactions of the<br />

group action.<br />

<strong>Semantics</strong><br />

Input: none<br />

Output: none<br />

Parameters: subaction:<strong>Action</strong>[0..*]<br />

The referenced actions may have control flow links (predecessor-successor) among themselves to specify the<br />

sequencing constraints among the actions.<br />

The actions in the set are executed concurrently, subject to the sequencing constraints among them. An action can<br />

execute when all its predecessors have executed. When all actions in the set have executed, execution of the concurrent<br />

set construct is complete.<br />

T: GroupToken; T. actionPtr->type = Group<strong>Action</strong><br />

Comment: must keep track of the set of statements that have been executed because of precedence constraints,<br />

therefore need a set of tokens or other markers of size O(statements)<br />

Precondition: T.status = ready<br />

Postcondition: T.status' = executing<br />

T.subtoken' = {for each S in P.statement => new U: Token where U.actionPtr = S; U.status = unready}<br />

Comment: to start the concurrent set, create a set of unready tokens, one for each statement in the set, and mark them<br />

as not having executed yet<br />

Precondition: T.status = executing; (there exists U in T.subtoken | U.status = unready;<br />

(for each Q in U.actionPtr.predecessor | there exists V in T.subtoken | V.actionPtr = Q and V.status = complete))<br />

Postcondition: U.status' = ready<br />

Comment: start executing a statement if its predecessors have completed and it has not yet been run<br />

Precondition: T.status = executing; (for each U in T.subtoken | U.status = complete)<br />

Postcondition: destroy T.subtoken' and its contents; T.status = complete<br />

Comment: the concurrent action is complete when all of its statements have executed<br />

Discussion<br />

Normal sequential execution is just a special case of concurrent execution in which the sequencing constraints<br />

form a list.<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 50


7 Composite <strong>Action</strong>s 7.5 Composite Classes<br />

Loop<strong>Action</strong><br />

Output: none<br />

Parameters: whileTest: Condition, body: <strong>Action</strong><br />

The condition is repeatedly evaluated. As long as it is true, the body action is executed. When is evaluates false,<br />

the loop is complete.<br />

<strong>Semantics</strong><br />

T: ConcurrentSetToken; T. actionPtr->type = ConcurrentSet<br />

Precondition: T.status = ready<br />

T: LoopToken; T.actionPtr->type = Loop<br />

Postcondition: T.status'= testing; new U: ConditionToken; T.test = U; U.actionPtr = P.whileTest; U.status = ready<br />

Comment: Start the test going<br />

Precondition: T.status = testing; T.test = U; U.status = passed<br />

Postcondition: destroy U'; T.status' = executing; new V: Token; T. body' = V; V.actionPtr = P.body; V.status = ready<br />

Comment: if the condition is true, execute the body<br />

Precondition: T.status = testing; T.test = U; U.status = failed<br />

Postcondition: T.status' = complete; destroy U''<br />

Comment: if the condition is false, the loop is complete<br />

Precondition: T.status = executing; T.body = V; V.status = complete<br />

Postcondition: T.status' = ready<br />

Comment: repeat the loop<br />

Loop<strong>Action</strong><br />

A loop action contains a single clause whose test action and body action are executed repeatedly as long as the test<br />

action outputs a “true” value. A special list of output pins acts as “loop variables” for the loop action. The loop variables<br />

are not directly available outside the loop. Input pins of the overall loop action provide initial values that are<br />

copied into these loop variables before the first iteration of the loop. As output pins, the loop variables may be connected<br />

to available inputs of the test and body actions using normal data flows, to provide the “old values” of the loop<br />

variables during an iteration. The outputs of the loop clause provide “new values” that are copied to the loop variables<br />

at the completion of an iteration. The test is executed after the initial values are copied to the loop variables, and also<br />

after each execution of the body action. The body action is executed only if the test outputs a “true” value. When the<br />

loop terminates, the final values of the loop variables are copied to the regular output pins of the loop action, which<br />

are the only available outputs for the loop action as a whole.<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 51


7 Composite <strong>Action</strong>s 7.5 Composite Classes<br />

Associations<br />

• clause The clause that contains the test and body actions for the loop.<br />

• loopVariable The set of loop-action output pins that act as loop variables for the loop. These are owned<br />

directly by the loop action, but they are not available outside the loop.<br />

Well-formedness rules<br />

[1] The clause of a loop action must have the same number of outputs as the number of loop variables of the loop and<br />

each clause output in the ordered list must conform to the corresponding loop variable in type and multiplicity.<br />

[2] A loop action must have the same number of inputs pins as loop variables and each input pin must conform to the<br />

corresponding loop variable in type and multiplicity.<br />

[3] A loop action must have the same number of output pins as the number of loop variables and each loop variable<br />

in the ordered list must conform to the corresponding output pin (in order) in type and multiplicity.<br />

[4] The test action of the clause of a loop action may not participate in any (explicit) control flows.<br />

[5] The set of available inputs of a loop action is the union of the available inputs of the test and body actions of the<br />

clause of the loop action that are not connected to loop variables and the loop-action input pins.<br />

[6] The available outputs of a loop action are the output pins of the loop action.<br />

[7] There may be no path from an output pin of a loop action to any action within the loop action (where a path is<br />

defined as in Rule [1] under <strong>Action</strong>).<br />

Map<strong>Action</strong><br />

Output: none<br />

Parameters: target: Collection of Object, mapop:Operation, input: Collection [0..*] of Value<br />

Constraints: The number and types of the arguments must be compatible with the operation.<br />

The operation is called concurrently on each object in the set of targets. When all of the calls are complete, the<br />

map action is complete. The operation must perform its work by side effects on the targets, as there are no return values<br />

Note that there is one target specification, which at run time must be a collection of objects. There is a list of<br />

input argument specifications, each of which at run time must be a collection of values of the same shape as the target<br />

collection. The number of input collections must equal the number of arguments in the operation. For each call on the<br />

operation, one value is taken from the target collection and from each input collection.<br />

Reduce<strong>Action</strong><br />

Output: Value<br />

Parameters: target: Collection of Object, redop:Operation<br />

Constraints: The redop type operation must be an operation on the type of objects in the collection, which must all be<br />

compatible with the type. The redop operation must be associative. Its arguments are a pair of target objects (or a<br />

target object and another of the same type as argument). The result of the reduce operation is also of the same type.<br />

The operation is applied to a pair of consecutive values and the result value conceptually replaces the two input<br />

values, reducing the size of the list. This procedure is repeated until only one value remains. This value is the result of<br />

the reduce action. Because the redop is associative, the result value is insensitive to the order in which the reduction is<br />

done (partial parallel execution is possible).<br />

Note that there is one target specification, which at run time must be a collection of objects. There is no collection<br />

of input values. The result is a single value.<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 52


7 Composite <strong>Action</strong>s 7.5 Composite Classes<br />

Test<strong>Action</strong> (implicit rules, not an explicit action)<br />

T: TestToken; T.actionPtr->type = Test<strong>Action</strong><br />

Comment: execute an action and return status passed or failed<br />

Precondition: T.status = ready<br />

Postcondition: new U: token; T.testBody' = U; T.status' = executing; U.status = ready<br />

Precondition: T.status = executing; U = T.testBody; U.status = complete<br />

Postcondition: destroy U'; if U.activation[P.flag] = true then T.status' = passed else T.status' = failed<br />

Discussion<br />

As part of the procedure structure, there are flow of control meta-actions that structure simple actions. These are<br />

concurrent sets (execute all the contained statements), exclusive sets (execute only one contained statement whose<br />

guard condition evaluates true), and loops (execute one statement repeatedly until the guard condition evaluates<br />

false). Control actions build larger actions out of smaller ones.<br />

Note that a condition itself is an action that may have structure. The result must be a boolean value and there<br />

must be no side effects.<br />

The presence of concurrency and overlapping conditions may lead to nondeterminism. That’s OK.<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 53


7 Composite <strong>Action</strong>s 7.5 Composite Classes<br />

composite<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 54


8 Access <strong>Action</strong>s 8.1 Read <strong>Action</strong>s<br />

Chapter 8. Access <strong>Action</strong>s<br />

These actions access values in object memory, that is, in the system state. The include actions to read and write<br />

attributes and links. Any of these actions may cause a conflict, therefore they must often be explicitly sequenced<br />

using control flows to avoid concurrent access on the same memory location.<br />

8.1. Read <strong>Action</strong>s<br />

Read actions include actions to read attributes and links. The input values identify the object from which to start the<br />

access and model elements to identify the navigation path (attribute or association end). If the multiplicity of the target<br />

location is many, a read action will produce a collection as its output.<br />

8.2. Write <strong>Action</strong>s<br />

Write actions include actions to write attributes and links. The input values identify the object from which to start the<br />

access and model elements to identify the navigation path (attribute or association end), as well as the value to be<br />

stored in the target location. There are no output values of a write action. If the multiplicity of the target location is<br />

many, a write action will produce a change (add an element or delete an element) to a collection of values.<br />

8.3. Access Classes<br />

The following metamodel shows the access classes.<br />

InputPin<br />

0..1 +index<br />

ReadAssociation<strong>Action</strong><br />

+feature 1<br />

AssociationEnd<br />

+sourceObject<br />

1<br />

Read<strong>Action</strong><br />

Attribute<br />

{1 result}<br />

ReadAttribute<strong>Action</strong><br />

+feature 1<br />

<strong>Action</strong><br />

Write<strong>Action</strong><br />

WriteAssociation<strong>Action</strong><br />

AssociationEnd<br />

Figure 15. Access classes metamodel<br />

+targetObject<br />

1<br />

+source<br />

InputPin<br />

1<br />

WriteAttribute<strong>Action</strong><br />

1 +feature<br />

1 +feature<br />

Attribute<br />

access<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 55<br />

0..1<br />

+index


8 Access <strong>Action</strong>s 8.3 Access Classes<br />

ReadAssociation<strong>Action</strong><br />

Output: Value<br />

Parameters: sourceObject: Object, feature:AssociationEnd, index:Value<br />

Constraints: The association (and index, if present) must be compatible with the declared type of the object. The<br />

association must be binary.<br />

The value associated with the source object across the link to the given association end is read and becomes the<br />

result. The read is subject to conflict.<br />

<strong>Semantics</strong><br />

Precondition: T.status = ready; P.index is empty<br />

Postcondition: A.resultValue[result]' = getlink (A.resultValue[P.object], P.feature); T.status' = complete<br />

where getlink (objectptr, associationEnd) means the value or collection of values (depending on multiplicity)<br />

associated with the given object across to the given end of the association<br />

Precondition: T.status = ready, P.index is not empty<br />

Postcondition: A.resultValue[result]’ = select (A.resultValue[P.object], P.feature, P.index); T.status' = complete<br />

where select (objectptr, associationEnd, index) means the value selected by the index value as a qualifier with the<br />

collection of values associated with the given object across to the given end of the qualified association<br />

ReadAttribute<strong>Action</strong><br />

Output: Value<br />

Parameters: sourceObject: Object, feature:Attribute, index:Value<br />

Constraints: The attribute (and index, if present) must be compatible with the declared type of the object.<br />

The value in the specified attribute of the source object is read and becomes the result. The read is subject to conflict.<br />

<strong>Semantics</strong><br />

Precondition: T.status = ready; P.index is empty<br />

Postcondition: A.resultValue[P.result]' = getattr (A.resultValue [P.sourceObject], P.feature); T.status' = complete<br />

where getattr (objectptr, attribute) means to get the value of the named attribute within the object<br />

Precondition: T.status = ready; P.source: AttributeNavigation, P.index is not empty<br />

Postcondition: A.resultValue[result]’ = index (A.resultValue[P.sourceObject], P.feature, P.index); T.status' = ready<br />

where index (objectptr, name, index) means to get the value of the given element of the list of values of the<br />

named attribute in the object<br />

WriteAssociation<strong>Action</strong><br />

Output: none<br />

Parameters: source: Value, targetObject: Object, feature: (AssociationEnd or Attribute), index: Value<br />

Constraints: The navigation must be compatible with the declared type of the object and the source value type must<br />

be compatible with the type of the association end (may be a scalar value or a collection, depending on multiplicity)<br />

The source value is stored as the value of the given link.<br />

access<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 56


8 Access <strong>Action</strong>s 8.3 Access Classes<br />

Note that there may be secondary effects to keep the multiplicity consistent if an association with non-unlimited<br />

multiplicity is updated.<br />

<strong>Semantics</strong><br />

Precondition: T.status = ready, P.index is empty<br />

Postcondition: getlink (A.resultValue[P.targetObject], P.feature)' = A.resultValue[P.source]<br />

where getlink (objectptr, associationEnd) means the value or collection of values (depending on multiplicity)<br />

associated with the given object across to the given end of the association<br />

and other links of the association are deleted as necessary to keep the multiplicities correct<br />

Precondition: T.status = ready, P.index is not empty<br />

Postcondition: select (A.resultValue[P.targetObject], P.feature, A.resultValue[P.index])' = A.resultValue[P.source]<br />

where select (objectptr, associationEnd, index) means the value selected by the index value as a qualifier with the<br />

collection of values associated with the given object across to the given end of the qualified association<br />

and other links of the association are deleted as necessary to keep the multiplicities correct<br />

This action must be reconciled with the manipulation actions that operate on links.<br />

WriteAttribute<strong>Action</strong><br />

Output: none<br />

Parameters: source: Value, targetObject: Object, feature: Attribute, index: Value<br />

Constraints: The navigation must be compatible with the declared type of the object and the source value type must<br />

be compatible with the attribute type<br />

The source value is stored as the value of the given attribute.<br />

<strong>Semantics</strong><br />

Precondition: T.status = ready; P.index is empty<br />

Postcondition: getattr (A.resultValue[P.targetObject], P.feature)' = A.resultValue[P.source]; T.status' = complete<br />

where getattr (objectptr, attribute) means the value of the named attribute within the object<br />

Precondition: T.status = ready, P.index is not empty<br />

Postcondition: index (A.resultValue[P.targetObject], P.feature, A.resultValue[P.index])' = A.resultValue[P.source]<br />

where index (objectptr, attribute, index) means the value of the given element of the list of values of the named<br />

attribute in the object<br />

access<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 57


8 Access <strong>Action</strong>s 8.3 Access Classes<br />

access<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 58


9 Manipulation <strong>Action</strong>s 9.1 Manipulation Classes<br />

Chapter 9. Manipulation <strong>Action</strong>s<br />

Manipulation actions create and destroy objects and links.<br />

9.1. Manipulation Classes<br />

The following metamodel shows the manipulation classes.<br />

+class<br />

1<br />

CreateObject<strong>Action</strong><br />

Class<br />

{ordered<br />

must match constructor}<br />

Association<br />

0..* +argument<br />

InputPin<br />

+association<br />

1<br />

<strong>Action</strong><br />

InputPin<br />

{1 result}<br />

DestroyObject<strong>Action</strong><br />

+target<br />

{ordered<br />

must match association}<br />

{may be wild card}<br />

+end 2..*<br />

LinkEndData<br />

+participant 1<br />

InputPin<br />

{object or set of objects}<br />

{2 results}<br />

CreateLink<strong>Action</strong><br />

FindLink<strong>Action</strong><br />

Figure 16. Manipulation classes metamodel<br />

{1 result}<br />

{1 result}<br />

DestroyLink<strong>Action</strong><br />

manipulation<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 59<br />

1<br />

{may be wild card}<br />

+qualifier<br />

0..1<br />

ManipulateLink<strong>Action</strong>


9 Manipulation <strong>Action</strong>s 9.1 Manipulation Classes<br />

CreateLink<strong>Action</strong><br />

Output: Link, Status<br />

Parameters: association:Association, end:LinkEndData[2..*]<br />

Constraints: The number of ends must match the rank of the association. The ends must be objects or objects with<br />

qualifier values, and their types must match the association.<br />

If a link of the given association is created with the given list of end values. If a link with that value already<br />

exists, nothing happens.<br />

The status indicates whether a new link was created.<br />

The action can conflict with DestroyLink and FindLink.<br />

If the resultant cardinality would be inconsistent with the declared multiplicity, existing links are destroyed if<br />

necessary to maintain the declared multiplicity. The link always exists after the step.<br />

It is not possible to simply abandon an attempted operation that would violate multiplicity, because cardinality<br />

would have to pass through illegal states to reach a legal value, therefore we cannot have a variant that simply rejects<br />

an attempt to set an incorrect multiplicity. That is why the action repairs inconsistencies in multiplicity.<br />

Discussion<br />

Link manipulation (creation, finding, navigating, editing, destroying) involves<br />

• creating links from the object at either end or as explicit tuples<br />

• multiplicity constraint maintenance: various options<br />

• n-ary links<br />

• changing links, including attributes<br />

• destroying links from either end or as tuples, effect on multiplicity maintenance<br />

Links may be created by specifying the association and a list of object references compatible with the association.<br />

Link attributes are initialized after creation of the link. This is all atomic. The objects are then pointed at the new<br />

link. [This is an opportunity for conflict if another activation attempts to create the same link or a conflicting link.]<br />

It makes no sense to talk about updating the two ends of a link independently, as if they were independent pointers.<br />

The object pointers in a link may not be changed. (Links don’t have identity apart from the list of values they<br />

relate.) In other words, you can’t just move the end of a link to point at a different object. The link must be destroyed<br />

and a new one created. The attribute values in an existing link may be modified without destroying the link, because<br />

the object pointers give identity to the link as a container of attribute values.<br />

This action works from the point of view of the association, whereas WriteAssociation works from the point<br />

of point of an object that participates in the association. Do we need both? Need to reconcile them.<br />

CreateObject<strong>Action</strong><br />

Output: Object<br />

Parameters: class:Class, argument:Value[0..*]<br />

Constraints: The argument values must match the arguments of the constructor of the class. The type of the result is<br />

the class.<br />

Identity for a new object is created, storage for the object of the given class is allocated and its type is set to the<br />

given class. Initial value expressions are evaluated for attributes of the object. The constructor for the class (if any) is<br />

called using the argument values. When initialization is complete, the identity of the new object is returned as the<br />

value of the action.<br />

Discussion<br />

manipulation<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 60


9 Manipulation <strong>Action</strong>s 9.1 Manipulation Classes<br />

Creates a new object involving the following tasks, not necessarily all in the same action:<br />

• create a new identity<br />

• allocate storage<br />

• initialize the contents<br />

• create subordinate objects<br />

Return the identity of the new object for storage in a variable. At this point its identity and storage exist. It is an<br />

open question whether it is fully initialized. This may be a user choice in the program.<br />

If it is an active object, then also:<br />

• create a new, empty event queue<br />

• create a root activation<br />

• start a token at the initial statement<br />

• make a create event for the new object using the arguments (this needs to be traded off against just running a constructor)<br />

Creation of a composite requires creation of its parts recursively.<br />

DestroyLink<strong>Action</strong><br />

Output: Status<br />

Parameters: association:Association, end:LinkEndData[2..*]<br />

Constraints: The ends must match the association in number and type.<br />

Any link of the given association whose ends match the values of the end arguments is destroyed. Some of the<br />

end values may be wild cards, which match any corresponding end value in a link. For example, DestroyLink (Works-<br />

For, (Joe, *)) destroys all of the employment links from Joe.<br />

The result indicates how many links were destroyed. (Other status formats are conceivable.)<br />

DestroyObject<strong>Action</strong><br />

Output: None<br />

Parameters: target: Object<br />

Constraints: The target object is destroyed. Any links involving it are destroyed.<br />

Semantic variation point. If the object is a composite in any links, the corresponding parts are destroyed<br />

recursively.<br />

Any token that is blocked doing a watch action on the destroyed object is unblocked.<br />

Discussion<br />

Destroys an existing object involving the following tasks, not necessarily all in the same action:<br />

• destroy subordinate objects<br />

• deallocate storage<br />

• mark the object as dead<br />

• deallocate the identity (some variations will never reuse identity)<br />

• notify requestors of its death<br />

If it is an active object, then also<br />

• stop or wait for execution to cease (there may be semantic variation points as to whether the stop is forced)<br />

• destroy all of its activations<br />

Destruction of an object implies destruction of any composite parts recursively.<br />

Destruction may be a source of conflict if multiple references are outstanding. This should preferably be prevented<br />

by the composition semantics, but it might still be a problem with references.<br />

manipulation<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 61


9 Manipulation <strong>Action</strong>s 9.1 Manipulation Classes<br />

FindLink<strong>Action</strong><br />

Output: Set of Link<br />

Parameters: association:Association, end:LinkEndData[2..*]<br />

Constraints: The ends must match the association in number and type.<br />

Returns a set of identity to links that match the list of ends. Some of the end values may be wild cards, which<br />

match any corresponding end value in a link. For example, FindLink (WorksFor, (Joe, *)) finds all of the employment<br />

links from Joe.<br />

The link identity can be navigated to find the participants, qualifier values, or link attribute values.<br />

ManipulateLink<strong>Action</strong> (abstract)<br />

Includes various kinds of link manipulation and searching actions.<br />

Output: depends on specific action subclass<br />

Parameters: association:Association, end:LinkEndData[2..*]<br />

The number of LinkEndData values and their structure (with or without qualifiers) must match the structure of<br />

the association. Each end value specifies a link end value to insert in a new link or to search for in an existing link. On<br />

a search, a WildCardValue indicates that any link end value is acceptable as a match, usually resulting in a set of<br />

matching links.<br />

manipulation<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 62


10 Computation <strong>Action</strong>s 10.1 Computation Classes<br />

Chapter 10. Computation <strong>Action</strong>s<br />

These actions transform a set of input values to produce a set of output values.<br />

10.1. Computation Classes<br />

The following metamodel shows the computation classes.<br />

{1..* results}<br />

ApplyFunction<strong>Action</strong><br />

+input 0..*<br />

{ordered}<br />

InputPin<br />

1 +function<br />

PrimitiveFunction<br />

name : Name<br />

definition : Undefined<br />

+inputType 0..* 1..* +resultType<br />

Classifier<br />

Figure 17. Computation classes metamodel<br />

ApplyFunction<strong>Action</strong><br />

Compute a primitive predefined function without side effects.<br />

Output: Value[1..*] (number of results and result types depend on the specific primitive function)<br />

Parameters: function:PrimitiveFunction, input:Value [0..*]<br />

Constraints: The input and result types of the arguments must match the declared types in the primitive function<br />

definition in number and type (subject to normal polymorphism rules).<br />

Description: Applies the primitive function to the input values to yield a result value or values.<br />

There are absolutely no side effects of this action and it therefore cannot conflict with anything. All it does it produce<br />

result values using a mathematical function.<br />

New primitive functions may be defined (outside of <strong>UML</strong>) as mathematical functions of input values to output<br />

values. All usual primitive operations should be considered as primitive functions, e.g., addition, nand, square root,<br />

finding a substring, Bessel function, etc. A list of defined primitive functions may be supplied as part of a modeling<br />

profile.<br />

computation<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 63<br />

<strong>Action</strong><br />

Code<strong>Action</strong><br />

language : String<br />

encoding : String<br />

Null<strong>Action</strong><br />

{1 result}<br />

LiteralValue<strong>Action</strong><br />

+value<br />

DataValueIdentity<br />

(from Structure Model)


10 Computation <strong>Action</strong>s 10.1 Computation Classes<br />

<strong>Semantics</strong><br />

Precondition: T.status = ready<br />

Postcondition:<br />

where n is the number of inputs and m is the number of inputs to the function<br />

(for j=1..n) a[j] = A.resultValue [P.input[j]]<br />

(for i=1..m) b[i] = fj (a[1], a[2], ..., a[n])<br />

A.resultValue[P.result[i]]' = b[i]<br />

T.status' = complete<br />

Comment:<br />

The a and b values are temporary identifiers within the semantics expression<br />

The result designators A.resultValue[i] must all be distinct (no aliasing).<br />

The primitive function must define a family of functions fj(x1, x2, ..., xn) whose value types match the argument<br />

and result values.<br />

Note: The literal value action could have been defined as a primitive function (no inputs, one output), but it seems<br />

common enough to provide directly without the bother of defining functions.<br />

Discussion<br />

• multi-input, multi-output, using local variables as parameters<br />

• no effect or access to object state<br />

• arbitrary mathematical functions (not just a few built-in primitives)<br />

• predefined number of parameters<br />

Apply actions are specified as pure functions from a list of input values to a list of output values, both of which<br />

are stored in local variables of an activation. This separates functional computation from data manipulation and flow<br />

of control issues. By necessity, a call on a method cannot be a functional step, as it includes all of these aspects.<br />

We permit arbitrary definition of functions (within reason) rather than defining a primitive language. This seems<br />

the only way to avoid defining yet another programming language or tilting toward an existing programming language.<br />

It may be necessary to define a canonical set of basic functions, however, for ease of interchange (but not<br />

needed for semantics). Functions operate on scalar values, because collections are stored as objects. Therefore there<br />

are no functions on collections (but operations on collections can be constructed as actions at a higher level out of<br />

functional pieces).<br />

Functions have no effect on and may not access object state.<br />

Semantic variation point. Stuck function: whether a function may fail to terminate and require interruption. At a<br />

first glance, we would expect primitive functions to always complete, but this may not be true.<br />

Functions may raise exceptions which trigger the exception mechanism. These must be predefined as part of their<br />

range of results (need to add to operations, methods, and primitive functions.<br />

Code<strong>Action</strong><br />

Output: none<br />

Parameters: language:String, encoding:String<br />

Constraints: The constraints and effects of this statement are implementation dependent. They must be defined by the<br />

particular implementation, and they provide an opportunity to tailor the semantics.<br />

<strong>Semantics</strong><br />

Cannot be defined in <strong>UML</strong>. Must be defined by the extender.<br />

computation<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 64


10 Computation <strong>Action</strong>s 10.1 Computation Classes<br />

Precondition: T.status = ready<br />

Postcondition: T.status' = complete<br />

Other changes as specified by the implementation-specific code<br />

LiteralValue<strong>Action</strong><br />

Output: DataValueIdentity<br />

Parameters: value: DataValueIdentity<br />

Generates a literal value. The value can be of any pure data type.<br />

Precondition: T.status = ready<br />

Postcondition: T.status = complete; A.resultValue[P.result[1]]' = P.value<br />

Null<strong>Action</strong><br />

Output: none<br />

Parameters:<br />

There is no effect of executing this action.<br />

precondition: T.status = ready<br />

postcondition: T.status' = complete<br />

computation<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 65


10 Computation <strong>Action</strong>s 10.1 Computation Classes<br />

computation<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 66


11 Interaction <strong>Action</strong>s 11.1 Interaction Classes<br />

These actions cause interactions among objects.<br />

11.1. Interaction Classes<br />

Chapter 11. Interaction <strong>Action</strong>s<br />

The following metamodel shows the interaction classes.<br />

InputPin<br />

Spawn<strong>Action</strong><br />

{0 result}<br />

{ordered}<br />

+input<br />

0..*<br />

1 +targetObject<br />

Invocation<strong>Action</strong><br />

Call<strong>Action</strong><br />

{0..* results}<br />

Terminate<strong>Action</strong><br />

<strong>Action</strong><br />

Send<strong>Action</strong><br />

+argument 0..*<br />

+target<br />

1<br />

{object set}<br />

{must match signal}<br />

InputPin<br />

Figure 18. Interaction classes metamodel<br />

+signal<br />

Signal<br />

interaction<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 67<br />

1<br />

Watch<strong>Action</strong><br />

{object set}<br />

1 +target<br />

InputPin


11 Interaction <strong>Action</strong>s 11.1 Interaction Classes<br />

Call<strong>Action</strong><br />

Call an operation.<br />

Output: Value[0..*]<br />

Parameters: targetObject: Object, operation: Operation, input: Value [0..*]<br />

Constraints: The number and types of argument and return values must match the number and types of the declared<br />

parameters of the operation. Normal polymorphism rules apply. The operation must be defined for the declared class<br />

of the target argument.<br />

Description: The current token is set to executing status and a new activation is created whose hostPtr is the target<br />

object, whose local variables are copied from the arguments (with names from the operation declaration), and whose<br />

token is set to the start of the method found by searching the operation in the actual class of the target object. When<br />

the execution of the created activation terminates, the return values (if any) are copied back to the result values and<br />

the current token is set to active states and advanced to the next statement.<br />

<strong>Semantics</strong><br />

Precondition: T.status = ready<br />

Precondition:<br />

new AA: Activation<br />

new U: Token<br />

T.status' = executing<br />

T.dependent' = T.dependent + AA — addition of an element to a set<br />

AA.caller = T<br />

AA.host = A.resultValue [P.targetObject]<br />

AA.token = Set {U}<br />

AA.resultValue = empty table<br />

AA.name = empty table<br />

(for i=1..n) AA.parameter[P.operation.parameter[i].name] = A.resultValue [P.input[i]]<br />

{ need to handle default parameters, but they are just a kind of sugaring, also initialize return parameters }<br />

U.status = ready<br />

program: <strong>Action</strong> = method-lookup (AA.host, P.operation)<br />

U.actionPtr = program<br />

Comment: operation.parameter[i] represents the i’th parameter designated as an input parameter. We assume that all<br />

parameters are input or return parameters. We ignore out and in-out parameters and treat them as programminglanguage<br />

sugarings, and we propose that they be removed from core <strong>UML</strong>.<br />

macro method-lookup (object: Object, operation: Operation)<br />

let found-methods = empty set<br />

let C-set =object.class (the type of the actual runtime object, a set of classes)<br />

let c-all = the classes in C-set together with all of their ancestor classes<br />

for each class C in C-all, if operation has a matching method in C,<br />

add the method to found-methods<br />

eliminate any method whose class is an ancestor of another method in found-methods<br />

if there is exactly only method in the set, it is the target method<br />

interaction<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 68


11 Interaction <strong>Action</strong>s 11.1 Interaction Classes<br />

if there are no methods in the set, there is an error (method not found)<br />

if there are two or more methods in the set, there is a conflict error<br />

MUST WRITE SEMANTICS FOR CALL EVENTS AND THEIR RETURNS<br />

Call return (implicit action)<br />

U.status = complete; AA.token = {U} — U is the only remaining token in the activation<br />

T = AA.caller<br />

Postcondition:<br />

destroy AA' and all its contents (values and tokens)<br />

T.dependent' = T.dependent - AA — set subtraction<br />

(for i=1..n) T.activation.resultValue [T.actionPtr.result[i]]' = AA.parameter[T.actionPtr.operation.parameter<br />

[ret(i)]], where ret(i) denotes the index of the i’th return parameter within the operation’s parameters<br />

T.status' = complete<br />

Comment: This is the implicit action at the conclusion of a normal call.<br />

Precondition:<br />

U.status = complete; AA.token = {U} — U is the only remaining token in the activation<br />

AA.caller = null — root activation<br />

Postcondition:<br />

destroy AA' and all its contents (values and tokens)<br />

Comment: This is the cleanup for a spawned activation.<br />

Discussion<br />

A call creates a new activation with a return pointer to the calling activation and blocks the calling token (it waits for<br />

the completion of the called activation). The new activation receives the list of arguments specified in the call as its<br />

parameter values and its host object pointer is set to the target object. A token is created with its action pointer set to<br />

the enclosing action for the method. Usually this action is a composite set action that includes the individual actions<br />

that compose the method.<br />

If the called operation is marked for a call event, then a signal is sent to the target object instead of creating a new<br />

activation. The signal has a return pointer to the calling activation, which is still blocked.<br />

Completion of the called activation terminates and destroys the current activation and completes the calling<br />

action. Similarly, completion of the action (including a null action) on the transition triggered by a call event, or the<br />

failure to trigger any transition after handling a call event, sends a return packet to the calling activation.<br />

Interrupt<strong>Action</strong><br />

Output: none<br />

Parameters: target: <strong>Action</strong>Result(ActiveObject), exception:Exception, argument:<strong>Action</strong>Result[0..*]<br />

Constraints: The list of argument values must be compatible with the exception.<br />

An interrupt is transmitted to the active object (this may take time). When it is received, each active token of the<br />

active object performs the exception after completing any step in progress. The exception is handled as if it had been<br />

raised internally.<br />

Discussion<br />

interaction<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 69


11 Interaction <strong>Action</strong>s 11.1 Interaction Classes<br />

Causes the exception to occur in the activation(s) of the active object with the given arguments. This can be used to<br />

ask an active object to die but give it a chance to clean up properly (“soft kill”).<br />

Raise<strong>Action</strong><br />

Output: none<br />

Parameters: exception:Exception, argument: <strong>Action</strong>Result[*]<br />

Constraints: The argument types and number must be compatible with the exception.<br />

An instance of the exception with the given values occurs for the token. If the innermost action being executed has a<br />

handler for the exception, the token sets its program pointer to the handler and continues. Otherwise control passes to<br />

the end of the current action and the exception is handled by the next control action, until some action handles the<br />

exception or the outermost action is reached, which destroys the active object.<br />

An unhandled exception within a concurrent action set causes termination of concurrent activity.<br />

Poorly designed exceptions can obviously cause a lot of trouble, so they should be used with care.<br />

Discussion<br />

Exceptions are implicit actions that are performed during synchronous computation when some condition is met. This<br />

is usually deemed to be an “error” condition, often one that would prevent the normal action from being completed,<br />

so the exception effectively permits defining the action for all its input values. Exceptions are synchronous with the<br />

actions that cause them and cannot conflict with them. They are not signals. They can also be raised explicitly by an<br />

action and can be caused externally by an interrupt action.<br />

An exception is handled by terminating the current action and taking the exception handler clause matching the<br />

given exception. If there is no exception handler clause matching the given exception, control passes to enclosing<br />

actions until one is found to handle the exception. This could force the killing of concurrent tokens if an action set<br />

contains them. If control reaches the top action without finding a handler, the activation terminates and the exception<br />

propagates to the caller until it is handled.<br />

Send<strong>Action</strong><br />

Output: none<br />

Parameters: target: <strong>Action</strong>Result(Set of Object), signal:Signal, argument: <strong>Action</strong>Result[*]<br />

Constraints: The number and types of arguments must be compatible with the signal.<br />

A signal is created and initialized with the given values and sent to each object in the target set. A separate copy of the<br />

signal is sent to each object. There are no guarantees about transmission time, and it may vary for objects in the target<br />

set.<br />

<strong>Semantics</strong><br />

next T'<br />

(for j=1..n) some time later, separately for each j:<br />

Heap[target[j]].eventQueue.eventInstance' contains E[j],<br />

where E[j] is an SignalInstance that is an instance of signal,<br />

E[j].(T.signal.parameter[i].name) = T.argument[i]<br />

Discussion<br />

Forms a signal packet and transmits it to the target active object. When the packet arrives at the target active object, it<br />

is added to the event queue.<br />

interaction<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 70


11 Interaction <strong>Action</strong>s 11.1 Interaction Classes<br />

Signal (from core)<br />

A class of information communicated asynchronously as a unit from an object to an active object. A signal has a set<br />

of attributes, which can equivalently be interpreted as a list of parameters. The receipt of a signal by an active object<br />

is an event that is added to its event queue. The communication of signals among objects may take time.<br />

Spawn<strong>Action</strong><br />

Output: none<br />

Parameters: targetObject: Object, operation: Operation, input: Value [0..*]<br />

Constraints: The number and types of argument and return values must match the number and types of the declared<br />

parameters of the operation. Normal polymorphism rules apply. The operation must be defined for the declared class<br />

of the target argument.<br />

Description: A new activation is created whose hostPtr is the target object, whose local variables are copied from the<br />

arguments (with names from the operation declaration), and whose token is set to the start of the method found by<br />

searching the operation in the actual class of the target object. The calling token continues with its execution. When<br />

the execution of the created activation terminates, it is simply destroyed; no return values are transmitted.<br />

<strong>Semantics</strong><br />

Precondition: T.status = ready<br />

Precondition:<br />

new AA: Activation<br />

new U: Token<br />

T.status' = ready<br />

AA.caller = null<br />

AA.host = A.resultValue [P.targetObject]<br />

AA.token = Set {U}<br />

AA.resultValue = empty table<br />

AA.name = empty table<br />

(for i=1..n) AA.parameter[P.operation.parameter[i].name] = A.resultValue [P.input[i]]<br />

{ need to handle default parameters, but they are just a kind of sugaring, also initialize return parameters }<br />

U.status = ready<br />

program: <strong>Action</strong> = method-lookup (AA.host, P.operation)<br />

U.actionPtr = program<br />

Comment: operation.parameter[i] represents the i’th parameter designated as an input parameter. We assume that all<br />

parameters are input or return parameters. We ignore out and in-out parameters and treat them as programminglanguage<br />

sugarings, and we propose that they be removed from core <strong>UML</strong>.<br />

Terminate<strong>Action</strong><br />

Output: none<br />

Parameters:<br />

The current active object dies.<br />

interaction<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 71


11 Interaction <strong>Action</strong>s 11.1 Interaction Classes<br />

Discussion<br />

A terminate (i.e., suicide) is mostly easily done by the root activation running off the end, but probably a lower-lever<br />

activation might be able to terminate the active object—or maybe this is not necessary. On termination (suicide or<br />

murder), a signal is sent to those other threads who have requested notification.<br />

Knowledge of an active object is equivalent to having a link to it, so the issue of dangling active objects is the<br />

same as the issue of dangling pointers. There is the possibility of conflict.<br />

Watch<strong>Action</strong><br />

Output: none<br />

Parameters: target: <strong>Action</strong>Result(Object)<br />

The token blocks until the target object dies.<br />

Discussion<br />

The caller is added to the list of active objects that will resume when the target active object dies.<br />

Other kinds of notification might make sense at the engineering level, such as time-outs, etc.<br />

interaction<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 72


12 Primitive Communication <strong>Action</strong>s 12.1 Primitive Communication Classes<br />

Chapter 12. Primitive Communication <strong>Action</strong>s<br />

These actions support low-level communication among tokens without the large mechanisms needed to support active<br />

objects. These actions are intended to permit defining more complicated actions, such as state machine execution and<br />

interobject signal sending, without having to impose the complexities of those more complicated actions on the base<br />

execution machinery. These actions may also be useful directly in real-time work and other cases.<br />

12.1. Primitive Communication Classes<br />

The following metamodel shows the primitive communication classes.<br />

+argument 0..*<br />

Notify<strong>Action</strong><br />

Output: none<br />

InputPin<br />

Notify<strong>Action</strong><br />

+signal 1<br />

Signal<br />

<strong>Action</strong><br />

Wait<strong>Action</strong> Poll<strong>Action</strong><br />

Figure 19. Primitive communication classes metamodel<br />

Parameters: queue:SimpleQueue, signal:Signal, argument: <strong>Action</strong>Result[0..*]<br />

Constraints: The number and types of arguments must be compatible with the signal.<br />

A signal instance is created and initialized with the given values and added to the queue. The location where the<br />

signal instance is inserted in the queue may be specified by a subclass of SimpleQueue, but in the general case it is<br />

unspecified and no assumptions should be made. However, the queue maintains the order of events added to it. A<br />

first-in first-out policy is consistent with these rules.<br />

The action may take time, but the signal instance will be on the queue when the action completes. In particular, a<br />

subsequent Dequeue<strong>Action</strong> will find the event unless it has been subsequently removed from the queue.<br />

primitiveCommunication.fm Version 9 December 17, 1999 5:04 pm 73


12 Primitive Communication <strong>Action</strong>s 12.1 Primitive Communication Classes<br />

More than one token may attempt to notify the same queue, and all of them will succeed, but the relative order in<br />

which they are added is indeterminate. A queue serializes notify actions. It is a synchronizer.<br />

<strong>Semantics</strong><br />

Precondition: T.status = ready<br />

Postcondition: T.status' = completed<br />

P.queue.event' = P.queue.event + instantiate (signal, argument)<br />

where instantiate creates and initializes a new object of the given class and constructor values.<br />

Poll<strong>Action</strong><br />

Output: Event<br />

Parameters: queue: SimpleQueue<br />

Takes an event from the queue and make it the result, if the queue contains at least one event, otherwise produces<br />

the null value as the result. The event is removed from the queue. This action always completes immediately without<br />

waiting for a new event to arrive.<br />

Precondition: T.status = ready; there exists e:Event in queue.event<br />

Postcondition: T.status = complete; queue.event' = queue.event - e; result = e<br />

Precondition: T.status = ready; queue.event is empty<br />

Postcondition: T.status = complete; result = null<br />

Wait<strong>Action</strong><br />

Output: Event<br />

Parameters: queue: SimpleQueue<br />

Takes an event from the queue, if it contains at least one, otherwise waits until the queue receives an event and<br />

then takes it. The event is removed from the queue.<br />

Only one wait action may be outstanding at a time. A second wait action is an error to be handled in an implementation-specified<br />

manner (such as causing an exception).<br />

Precondition: T.status = ready; there exists e:Event in queue.event<br />

Postcondition: T.status = complete; queue.event' = queue.event - e; result = e<br />

Precondition: T.status = ready; queue.event is empty<br />

Postcondition: T.status' = executing<br />

Comment: For this action, status executing means that it is waiting for an event.<br />

Precondition: T.status = executing; there exists e:Event in queue.event<br />

Postcondition: T.status' = complete; queue.event' = queue.event(at time t) - e; result = e<br />

Precondition: T.status = ready; queue.waiter is nonempty<br />

Postcondition: ill-formed model error<br />

primitiveCommunication.fm Version 9 December 17, 1999 5:04 pm 74


13 Exception <strong>Action</strong>s 13.1 Exception and Interrupt Handling Classes<br />

Chapter 13. Exception <strong>Action</strong>s<br />

These actions invoke the exception and interrupt handling mechanisms.<br />

13.1. Exception and Interrupt Handling Classes<br />

The following metamodel shows the exception and interrupt handling classes.<br />

{ActiveObject}<br />

+target 1<br />

Interrupt<strong>Action</strong><br />

0..*<br />

InputPin<br />

0..1<br />

+argument<br />

+interrupt<br />

1<br />

exception : Exception<br />

Interrupt<br />

Signal<br />

<strong>Action</strong><br />

+exceptionHandler<br />

Exception<br />

Figure 20. Exception and interrupt handling classes<br />

Exception<strong>Action</strong> (implicit)<br />

An exception occurs when some exception condition stated in the description of an action occurs. The exception contains<br />

a list of values describing the nature of the occurrence. The execution of the action is aborted and the exceptionhandling<br />

mechanism is invoked.<br />

Interrupt<strong>Action</strong><br />

An action can send an interrupt to an active object. The interrupt action includes an exception as a parameter. When<br />

the interrupt is received, the active object raises the given exception in each of its active tokens. The exception occurs<br />

between steps. {Perhaps interrupts might need levels of atomicity, so that they occur at clean times, but that is a<br />

detail.] Each activation then has the opportunity to finish up and exit cleanly, even if it is executing a run-to-completion<br />

step (the interrupt breaks into the RTC step). If the exception is not handled, it propagates to a higher level as<br />

with other exceptions. If it reaches the outer level, the thread dies.<br />

exception<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 75<br />

0..1<br />

interrupt : Interrupt<br />

0..1<br />

+interruptHandler<br />

1 +exception<br />

0..1<br />

{ActiveObject}<br />

Raise<strong>Action</strong><br />

+target<br />

1<br />

InputPin<br />

+argument<br />

0..*


13 Exception <strong>Action</strong>s 13.1 Exception and Interrupt Handling Classes<br />

Implementing interrupts requires dependent pointers so that the interrupt can be propagated downward to all the<br />

leaf activations.<br />

Kill<strong>Action</strong><br />

An action can kill the active object outright, which cleans up all of its subordinate detail. This is an extreme measure<br />

because it does not execute the cleanup (exit actions, etc.) in the target state machine. When the active object receives<br />

the event, the transition forces exit of inner states and goes to the termination state. This can probably be treated by<br />

using an interrupt with an exception that cannot be handled.<br />

Reflective actions on active objects. It has been suggested that applications need some degree of reflective control on<br />

active objects, such as querying status, setting priorities, suspending or resuming execution, etc. These would seem to<br />

be appropriate actions, but it is unclear how to enumerate them, as they seem somewhat implementation-dependent.<br />

Probably they are part of an implementation and do not belong in the core execution semantics.<br />

Raise<strong>Action</strong><br />

An action that explicitly raises an exception in the current action. The normal exception-handling mechanism is<br />

invoked.<br />

exception<strong>Action</strong>s.fm Version 9 December 17, 1999 5:04 pm 76


IV Appendices<br />

Part IV. Appendices<br />

part-appendices.fm Version 9 December 17, 1999 5:04 pm 77


IV Appendices<br />

part-appendices.fm Version 9 December 17, 1999 5:04 pm 78


A Examples of Program Specifications<br />

Appendix A. Examples of Program Specifications<br />

This chapter contains examples illustrating the use of actions in sample models.<br />

programExamples.fm Version 9 December 17, 1999 5:04 pm 79


A Examples of Program Specifications<br />

programExamples.fm Version 9 December 17, 1999 5:04 pm 80


A<br />

Activation 19<br />

activation 17<br />

E<br />

execution instance model 7<br />

L<br />

link 7, 8, 56<br />

Index<br />

<strong>Action</strong> <strong>Semantics</strong>IX.fm Version 9 December 17, 1999 5:09 pm 81


<strong>Action</strong> <strong>Semantics</strong>IX.fm Version 9 December 17, 1999 5:09 pm 82

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!