language design rationale and semantic framework for

144
Language Design Rationale and Semantic Framework for Concurrent Object-Oriented Programming La Conception et la Description de la Sémantique des Langages Concurrents à Objets Michael Papathomas Genève 1992

Upload: vuongdieu

Post on 23-Dec-2016

225 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Language Design Rationale and Semantic Framework for

Language Design Rationale andSemantic Framework for ConcurrentObject-Oriented Programming

La Conception et la Description de la Sémantique

des Langages Concurrents à Objets

Michael Papathomas

Genève 1992

Page 2: Language Design Rationale and Semantic Framework for

Language Design Rationale andSemantic Framework for ConcurrentObject-Oriented Programming

La Conception et la Description de la Sémantique

des Langages Concurrents à Objets

Michael Papathomas

Genève 1992

Page 3: Language Design Rationale and Semantic Framework for

Michael Papathomas

L’application de l’approche de programmation par objets pour des applications concurrentes né-

cessite d’une part, des langages de programmation intégrant les concepts de la programmation

par objets à ceux de la programmation concurrente et d’autre part, afin de permettre leur réutili-

sation et évolution, une description précise du comportement des objets concurrents et une no-

tion formelle de comportement compatible.

Nous développons un cadre conceptuel, consistant en une typologie des choix de concep-

tion des langages et un ensemble de critères d’intégration de la programmation concurrente à la

programmation par objets, nous permettant d’évaluer les différentes combinaisons de choix de

conception. Puis, nous proposons une approche pour la description formelle de la sémantique

des langages concurrents à objets qui nous permet de représenter les différents choix de concep-

tion des langages et d’obtenir une notion formelle du comportement des objets concurrents.

Language Design Rationale and Semantic Framework for

Concurrent Object-Oriented Programming

La Conception et la Description de la Sémantique

des Langages Concurrents à Objets

Page 4: Language Design Rationale and Semantic Framework for

UNIVERSITÉ DE GENÈVEDépartement d’Informatique

FACULTÉ DES SCIENCESProfesseur C.PELLEGRINI

Language Design Rationale andSemantic Framework for

Concurrent Object-Oriented Programming

THÈSE

Présentée à la Faculté des Sciences de l’Université de Genève

pour obtenir le grade de Docteur ès Sciences mention Informatique

par

Michael PAPATHOMAS

de

Athènes, Grèce

Thèse No 2522

Genève 1992

Page 5: Language Design Rationale and Semantic Framework for

La Faculté des Sciences, sur le préavis de Messieurs C. PELLEGRINI, professeur ordinaire et

directeur de thèse (Département d’informatique), D. TSICHRITZIS, professeur ordinaire et co-

directeur de thèse (Faculté des Sciences économiques et sociales - Centre Universitaire d’Infor-

matique), A. YONEZAWA, professeur (Université de Tokyo) et O.M. NIERSTRASZ, docteur

(Faculté des Sciences économiques et sociales - Centre Universitaire d’Informatique), autorise

l’impression de la présente thèse, sans exprimer d’opinion sur les propositions qui y sont énon-

cées.

Genève, le 6 janvier 1992

Thèse No 2522

Le Doyen, Pierre BURI

© Michael Papathomas 1992. Tous droits réservés

Page 6: Language Design Rationale and Semantic Framework for

Remerciements

Il y a un certain nombre de personnes qui ont joué un rôle important pour la réalisation de ce

travail et auxquelles j’aimerais exprimer ma gratitude.

Je remercie le Professeur D. Tsichritzis pour avoir suivi et soutenu ce travail depuis le dé-

but ainsi que pour sa confiance. Il m’a permis non seulement d’accomplir cette thèse mais aussi

d’élargir considérablement mes connaissances.

Je remercie le Professeur C. Pellegrini pour avoir accepter la direction de cette thèse et

avoir rendu possible ça réalisation.

Je remercie le Professeur A. Yonezawa pour m’avoir fait l’honneur de faire partie du jury

ainsi que pour son encouragement.

J’ai plusieurs raisons pour remercier le Docteur O.M. Nierstrasz. J’aimerais le remercier

plus particulièrement pour m’avoir fait connaître le calcul des processus, pour avoir lu et com-

menté plusieurs versions antérieures de cette thèse et pour avoir été toujours prêt à s’engager

dans des discussions stimulantes.

Je remercie L. Dami et J. Vitek pour leur encouragement qui a été inestimable ainsi que

pour leurs commentaires et suggestions qui m’ont permis d’améliorer considérablement la pré-

sentation de mon travail.

Enfin, j’aimerais remercier mes parents, amis et collègues pour avoir été patients et com-

préhensifs envers moi pendant la durée de ce travail.

Page 7: Language Design Rationale and Semantic Framework for

6 Remerciements

Page 8: Language Design Rationale and Semantic Framework for

Acknowledgments

There is a number of people that played an important role in the accomplishment of this work to

whom I would like to express my gratitude.

I would like to thank Professor Tsichritzis, who followed my work from the very start, for

trusting me and providing me with the necessary support for this thesis. He allowed me not only

to accomplish this work but also gave me the opportunity to learn a lot.

I would like to thank Professor C. Pellegrini who by accepting the direction of this thesis

made it possible for me to carry out this work.

I would like to thank Professor A. Yonezawa for doing me the honor of accepting to be my

external reader and for his encouragement for this and future work.

There are several reasons for thanking Doctor O.M. Nierstrasz. To make a long story short,

I would like to thank him, among others, for getting me interested, a long time ago, in process

calculus, for reading and commenting on several earlier versions of this thesis and for being al-

ways ready to engage in stimulating discussions.

I would also like to thank L. Dami and J. Vitek for their encouragement, which has been

invaluable, and their acute comments and suggestions that allowed me to dramatically improve

the presentation of this work.

Finally, there is a large number of people, my parents and colleagues among others, that

had to endure the peculiar moods into which I was often driven during this period and whom I

would like to thank for their understanding.

Page 9: Language Design Rationale and Semantic Framework for
Page 10: Language Design Rationale and Semantic Framework for

Contents

Résumé 1

1 Introduction ..................................................................................................................1

1.1 La Conception des Langages à Objets Concurrents ...........................................1 1.2 La Spécification de la Sémantique des Objets Actifs .........................................2 1.3 Contributions ......................................................................................................3

2 Choix de Conception pour des Langages à Objets Concurrents .................................3

2.1 Le Modèle d’Objets ............................................................................................4 2.2 Les Fils de Contrôle............................................................................................4 2.3 L’Interaction des Objets......................................................................................5 2.3.1 Emission des Requêtes...............................................................................5 2.3.2 Acceptation des Requêtes ..........................................................................5

3 Comparaison des Choix de Conception .......................................................................6

3.1 Critères de Conception........................................................................................6 3.2 Evaluation des Choix de Conception..................................................................7 Modèles d’Objets............................................................................................7 Mécanismes d’Interaction et Fils de Contrôle ................................................7

4 Description Sémantique des Langages à Objets Concurrents ......................................8

5 Conclusion ...................................................................................................................9

CHAPTER 1

Introduction 11

1.1 Object-Oriented Programming ...............................................................................12

Objects and Messages...................................................................................12 Classes and Class Inheritance .......................................................................13 Substitutability, Types, Subtypes and Polymorphism ..................................13

1.2 Designing Concurrent Object-Oriented Languages ...............................................15

1.3 Specifying the Semantics of Active Objects ...........................................................17

1.4 Contributions ..........................................................................................................18

1.5 Thesis Overview .....................................................................................................19

Page 11: Language Design Rationale and Semantic Framework for

2 Contents

CHAPTER 2

Issues in the Design and Implementation ofthe Concurrent Object-Oriented Language Hybrid 21

2.1 Overview of Hybrid ................................................................................................22

Object Types .................................................................................................22 Object Interaction and Concurrency .............................................................23

2.2 The Concurrency Features ......................................................................................26

2.2.1 Local Delays With Delay Queues..................................................................27 2.2.2 Remote Delays With Delegated Calls ...........................................................28 2.2.3 Using Delegated Calls and Delay Queues for Local Delays .........................29

2.3 An Implementation of The Hybrid Concurrency Model ........................................30

2.3.1 Implementing the Concurrency Model ..........................................................32 2.3.2 Efficiently Supporting the Active View of Objects.......................................32

2.4 The Integration of the Concurrency and Object-Oriented Features ........................33

2.4.1 Encapsulation and Intra-Object Concurrency................................................34 2.4.2 Combining Synchronization and Inheritance ...............................................35 2.4.3 Data Abstractions with Concurrent Implementations....................................36

2.5 Summary .................................................................................................................37

CHAPTER 3

A Design Space for Concurrent OOPLs 39

3.1 A Design Space for Concurrent OOPLs .................................................................40

3.2 Concurrent Object Models ......................................................................................40

3.3 Internal Concurrency ..............................................................................................41

3.4 Constructs for Object Interaction ............................................................................43

3.4.1 The Client’s View - Issuing Requests............................................................43 One-way Message Passing............................................................................44 Remote Procedure Call .................................................................................44 Proxies ..........................................................................................................45 3.4.2 The Server’s View - Constructs for Accepting Requests ..............................45 Unconditional acceptance .............................................................................45 Explicit acceptance .......................................................................................46 Activation conditions...................................................................................46 Reflective computation .................................................................................47

3.5 Classification of Existing Languages .....................................................................47

3.5.1 The Orthogonal Approach .............................................................................47 Smalltalk-80 .................................................................................................47 Emerald ........................................................................................................48 Trellis/Owl ...................................................................................................49 ConcurrentSmalltalk ....................................................................................51 SR .................................................................................................................53 3.5.2 The Heterogenous Approach .........................................................................55 PAL ..............................................................................................................55

Page 12: Language Design Rationale and Semantic Framework for

Contents 3

Eiffel // .........................................................................................................55 ACT++ .........................................................................................................56 3.5.3 The Homogeneous Approach ........................................................................58 ABCL/1 ........................................................................................................58 ABCL/R .......................................................................................................61 POOL-T and POOL2 ...................................................................................61 Hybrid ..........................................................................................................62 SINA ............................................................................................................633.6 Summary .................................................................................................................65

CHAPTER 4

Comparing the Design Alternatives with Respect to Software Reuse 69

4.1 Language Design Requirements for Reusability ....................................................70

4.2 Comparing the Language Design Choices ..............................................................71

4.2.1 An Example Application ...............................................................................71 4.2.2 Exploring the Language Design Space..........................................................73

4.3 Concurrent Object Models ......................................................................................73

4.4 Thread Structure and Object Interaction Mechanisms ............................................73

4.4.1 Sequential Objects .........................................................................................74 RPC...............................................................................................................74 One-Way Message Passing...........................................................................75 Build-in Support for Courier Proxies............................................................76 More Flexible Request/Reply Mechanisms..................................................77 4.4.2 Multi-threaded Objects ..................................................................................78 Quasi-Concurrent Approaches......................................................................78 Concurrent Approaches ................................................................................79

4.5 Compositionality and Finer Grain Reuse ................................................................80

4.6 Conclusions and Summary ....................................................................................82

CHAPTER 5

A Unifying Framework for Process Calculus Semantics ofConcurrent Object-Based Languages and Features 85

5.1 Basic Framework: objects, classes and messages ...................................................87

5.1.1 The Structure of Class Agents .......................................................................88 5.1.1.1 Program-Defined Classes .....................................................................88 5.1.1.2 Predefined Classes ................................................................................89 5.1.2 Remarks .........................................................................................................89 5.1.3 The Structure of Program Defined Objects ...................................................89 The Request Handler ....................................................................................90 Instance Variables.........................................................................................90 Method Agents..............................................................................................91 The Method Scheduler..................................................................................91 Self ................................................................................................................92 Objects ..........................................................................................................92

Page 13: Language Design Rationale and Semantic Framework for

4 Contents

5.2 Defining SCOOL, a Simple Concurrent Object-Oriented Language .....................92

5.2.1 Syntax and Informal Description of SCOOL ................................................92 Expressions ...................................................................................................93 Statements.....................................................................................................94 Declarations ..................................................................................................94 5.2.2 Semantics .......................................................................................................94 Class Declarations.........................................................................................94 Variable Declarations ...................................................................................95 Method Declarations.....................................................................................95 5.2.2.1 Expressions and Statements..................................................................96 Agents Representing Expressions.................................................................96 Statements and Sequential Composition.......................................................96 Semantics of Expressions .............................................................................97 Semantics of Statements ...............................................................................98 5.2.2.2 Predefined Object Classes ....................................................................99 Process Objects .............................................................................................99 Semaphores...................................................................................................99 Booleans........................................................................................................99 Integers........................................................................................................100

5.3 Accommodating Other Object Models .................................................................101

5.3.1 Modifying the Syntax ..................................................................................101 Declarations ................................................................................................101 Statements...................................................................................................102 Expressions .................................................................................................102 5.3.2 Semantics .....................................................................................................102 Class Declaration ........................................................................................102 Method Scheduling .....................................................................................102 Semantics of Statements .............................................................................102

5.4 Class Inheritance ...................................................................................................102

5.4.1 Extending SCOOL to Support Inheritance ..................................................104 5.4.2 Agent Definitions for Modelling Class Inheritance.....................................104 Semantics of Class Declarations.................................................................106 5.4.3 Overriding Superclass Methods, Self and Super .........................................106

5.5 Considering Other Process Calculi ......................................................................107

5.5.1 Modelling COOPL Features in theπ-Calculus............................................108 5.5.2 Usingπ-Calculus Ports to Represent Object Identifiers..............................109 5.5.3 Comparing Object Identifiers ......................................................................110 5.5.4 Primitive Objects and the Semantics of Expressions...................................110

5.6 Concluding Remarks .............................................................................................112

CHAPTER 6

Conclusion 115

6.1 Summary ...............................................................................................................116

6.1.1 Language Design Framework......................................................................116 6.1.1.1 Understanding the Language Choices ................................................116

Page 14: Language Design Rationale and Semantic Framework for

Contents 5

Object Models.............................................................................................116 Object Threads............................................................................................116 Object Interaction .......................................................................................117 6.1.1.2 Language Design Criteria ...................................................................117 6.1.2 Evaluating Design Choices and their Combinations ..................................118 Request and Reply Scheduling ...................................................................118 Internal Concurrency ..................................................................................119 6.1.3 Formally Specifying the Semantics of COOPLs and of Active Objects .....119

6.2 Open Problems and Future Research Directions ..................................................120

6.2.1 Taking Advantage of Class Inheritance in COOPLs...................................120 6.2.2 Object Behavior, Behavioral Equivalence and Substitutability...................121 6.2.3 Types as Behavioral Constraints for Active Objects ...................................122

References 125

Page 15: Language Design Rationale and Semantic Framework for
Page 16: Language Design Rationale and Semantic Framework for

Résumé

1 Introduction

La programmation par objets est une méthode de programmation qui consiste à construire des

logiciels structurés à l’aide d’un ensemble d’objets coopérants qui inter-agissent pour réaliser

les fonctions du logiciel. Cette approche de programmation suscite un intérêt croissant dans plu-

sieurs domaines de l’informatique car, d’une part, elle fournit un ensemble de concepts unifica-

teurs permettant d’intégrer plusieurs techniques de programmation dont les bénéfices sont déjà

largement reconnus, d’autre part, elle offre la possibilité de pouvoir réutiliser les objets, qui sont

des entités relativement autonomes, dans diverses applications.

Les bénéfices de cette méthode de programmation pour la construction du logiciel sont ex-

ploités par l’utilisation des langages de programmation à objets, qui rendent aisée la program-

mation selon cette méthode, ainsi que par des méthodes de conception, outils et environnements

de programmation qui ont comme but d’ appliquer, à grande échelle, cette approche pour la réu-

tilisation du logiciel.

La motivation de ce travail est d’élargir le domaine d’application de cette méthode de pro-

grammation et permettre de tirer parti de ses bénéfices dans la construction des systèmes con-

currents. Ceci nécessite la conception de langages de programmation à objets concurrents qui

intègrent les concepts de la programmation par objets à ceux de la programmation concurrente,

ainsi que le développement d’outils pour la description, d’une manière rigoureuse, de la séman-

tique de ces langages et du comportement des objets concurrents afin de permettre leur réutili-

sation effective.

1.1 La Conception des Langages à Objets Concurrents

Un grand nombre de notations a été utilisé pour la programmation concurrente. De plus, il y plu-

sieurs façons de combiner les concepts et les notations de la programmation concurrente à ceux

de la programmation par objets. Le problème qui se pose pour la conception des langages à ob-

jets concurrents est que une combinaison arbitraire des notations pour la programmation par ob-

Page 17: Language Design Rationale and Semantic Framework for

2 Résumé

jets et la programmation concurrente, ne posant pas de difficultés au niveau syntaxique, ne per-

met pas l’intégration au niveau des concepts ce qui est necessaire pour tirer les bénéfices de la

programmation par objets pour la construction du logiciel concurrent. Ce problème provient de

la non-orthogonalité des concepts sous-jacents à ceux deux types de programmation.

Afin, de concevoir des langages de programmation qui permettent d’intégrer la program-

mation par objets et la programmation concurrente il est nécessaire d’étudier l’ inter-action des

concepts sous-jacents à ces deux types de programmation et de développer des critères permet-

tant d’évaluer les diverses possibilités concernant le choix des notations.

1.2 La Spécification de la Sémantique des Objets Actifs

Le développement de modèles pour la description de la sémantique des langages à objets con-

currents, à part d’être un but en soi, présente un intérêt tout particulier dans le cadre de la pro-

grammation concurrente par objets en ce qui concerne, en vue de leur réutilisation, la description

rigoureuse du comportement des objets développés à l’aide des langages à objets concurrents,

que l’on appellera par la suite objets actifs.

La description de la sémantique des langages à objets concurrents et du comportement des

objets actifs n’a fait l’objet que d’un nombre restreint de travaux de recherche. De plus, dans ces

travaux les points suivants n’ont été traités que d’une façon limitée:

• La description dans un seul modèle de l’ensemble des concepts de la programmation

concurrente par objets permettant une étude rigoureuse de leur interaction. Les appro-

ches antérieures n’ont pas pris en compte la description de sémantique de l’héritage.

• Le développement d’un modèle permettant la description et comparaison des langa-

gesà objets concurrents adoptant des approches de conception différentes. Les descrip-

tion sémantiques se sont limitées à un seul langage. Il est difficile de généraliser ces ap-

proches pour la description de la sémantique d’autres langages, surtout dans le cas où ils

sont basés sur des approches de conception différentes.

• Spécifier la sémantique des définitions d’objets d’une façon indépendante de la séman-

tique des programmes dans lequel elles apparaissent de sorte qu’elle puisse être utilisée

comme représentation rigoureuse du comportement d’objets et permettre d’établir la

compatibilité des comportements. Ce point est essentiel afin de permettre la réutilisation

des objets est de bénéficier de l’abstraction des données.

Page 18: Language Design Rationale and Semantic Framework for

Résumé 3

1.3 Contributions

Les principales contributions de cette thèse sont: (1) Un cadre conceptuel pour l’étude de l’inter-

action de la programmation à objets et de la programmation concurrente permettant l’évaluation

des différentes approches de conception. (2) Un cadre formel pour la description de la sémanti-

que des langages à objets concurrents permettant de spécifier et comparer la sémantique des lan-

gages basés sur des approches de conception différentes et d’établir une notion formelle de com-

portement pour les objets actifs. Les points suivants résument les contributions spécifiques:

• Une étude de cas concernant l’intégration des concepts de la programmation par objets et de

la programmation concurrente, effectuée sur le langage Hybrid, qui a permis d’examiner

d’une façon concrète l’effet des choix de conception sur l’intégration de ces concepts.

• Une description de l’espace des choix de conception pour les langages à objets concurrents

permettant de représenter les possibilités de combiner les concepts de la programmation con-

currente a ceux de la programmations à objets.

• Un ensemble des critères permettant l’évaluation des choix de conception par rapport à l’in-

tégration des concepts de la programmation par objets à ceux de la programmation concurren-

te.

• L’identification d’un ensemble de façons de combiner certains choix de conception qui satis-

font ces critères.

• Le développement d’une approche cadre pour la description formelle de la sémantique des

langages à objets concurrents permettant de:

• Représenter les concepts de programmation à objets et de la programmation concurrente.

• Obtenir une notion formelle de comportement pour les objets actifs.

• Etablir des notions formelles de compatibilité de comportement.

2 Choix de Conception pour des Langages à Objets Concurrents

Pour pouvoir comparer le grand nombre des possibilités pour la conception des langages à objets

concurrents nous avons choisit de représenter les choix de conception en considérant les trois

aspects suivants:

• Le modèle d’objets: La prise en compte de l’exécution concurrente dans le concept d’objet

• Les fils de contrôle des objets: Le nombre, la création et commutation des fils de contrôle à

l’intérieur des objets

Page 19: Language Design Rationale and Semantic Framework for

4 Résumé

• L’interaction des objets: les mécanismes et notations permettant de spécifier l’envoi et la ré-

ception de messages par les objets.

2.1 Le Modèle d’Objets

On distingue les trois approches suivantes concernant la prise en compte de l’exécution concur-

rente dans les objets:

• Orthogonale: le concept d’objet est indépendant des concepts de la programmation concur-

rente. Les objets sont des entités passives dont les opérations sont exécutées par des fils de

contrôle concurrents.

• Homogène: Les objets sont considérés comme des entités actives qui reçoivent des requêtes

pour l’exécution de leurs opérations qu’ils exécutent en temps opportun.

• Hétérogène: Il y a des objets passifs et des objets actifs. Le langage assure la protection des

objets passifs en interdisant la construction de programmes où les opérations des objets pas-

sifs peuvent être exécutés par des fils de contrôle concurrents.

2.2 Les Fils de Contrôle

En considérant le nombre et la commutation des leurs fils de contrôle on caractérise les objets

comme:

• Séquentiels: Un seul fil de contrôle correspond à chaque objet.

• Quasi-concurrents: Un seul fil de contrôle est actif à l’intérieur d’un objet et la commutation

des fils de contrôle est spécifiée par le programmeur.

• Concurrents: Il y a plusieurs fils de contrôle s’exécutant, d’un point de vue conceptuel, en pa-

rallèle.

La création des fils de contrôle à l’intérieur des objets peut se dérouler suivant deux façons

non exclusives:

Par réception de message: la création des fils de contrôle est initiée par la réception d’un mes-

sage.On distinguera deux sous-cas exclusifs concernant la création des fils de contrôle par ré-

ception de message:

• Création contrôlée: la création de fils de contrôle peut être contrôlée par l’objet.

• Non-contrôlée:la création de fils de contrôle se passe automatiquement à l’arrivée d’un

message.

Page 20: Language Design Rationale and Semantic Framework for

Résumé 5

• création explicite: la création des fils de contrôle a lieu par l’exécution, par un fil de contrôle

actif, d’une instruction prévue à cet effet.

2.3 L’Interaction des Objets

Pour examiner les mécanismes permettant l’interaction des objets on va considérer séparément

les cas d’émission et de réception des requêtes par les objets se trouvant, respectivement, dans

les rôles de client et serveur.

2.3.1 Emission des Requêtes

On distingue entre les mécanismes qui incorporent ou non une notion de réponse à une requête:

• One-way messages: la notion de réponse n’est pas prise en compte par ces mécanismes. L’en-

voi et obtention de réponse a lieu à travers des messages qui au niveau du langage ne se dif-

férencient pas des messages utilisés pour des requêtes.

• Request/Reply: Ces mécanismes incorporent une notion de réponse à une requête. Il y a cepen-

dant des variations considérables en ce qui concerne le contrôle qui peut être exercé par le cli-

ent pour l’obtention de la réponse. On distingue les catégories suivantes de mécanismes re-

quest/reply:

• Remote procedure call: le client doit attendre pour l’obtention de la réponse de manière

synchrone.

• Par Proxies: le client ne pas obliger d’attendre la réponse, des objets intermédiaires, plus

ou moins explicites, sont utilisées comme pour l’obtention de la réponse. Le client ob-

tient la réponse, de manière asynchrone par rapport au serveur, par ces objets intermédi-

aires.

2.3.2 Acceptation des Requêtes

On distingue entre acceptationconditionnelle et non-conditionnelle. L’ acceptation non-condi-

tionnelle se caractérise par l’absence de mécanismes pour contrôler l’acceptation des requêtes.

La réception d’un message a comme effet l’exécution de l’opération correspondante conforme-

ment aux propriétés des fils de contrôle des objets.

Les approches suivantes peuvent être utilisées dans le cas de l’acceptation conditionnelle

pour contrôler l’acceptation des requêtes:

• Acceptation explicite: l’acceptation a lieu par l’exécution d’une instruction par un fil de con-

trôle de l’objet spécifiant explicitement les requêtes à accepter.

Page 21: Language Design Rationale and Semantic Framework for

6 Résumé

• Conditions d’activation: Les opérations sont associées à des conditions sur l’état de l’objet

qui doivent être satisfaites pour l’acceptation et exécution d’une requête. Les conditions sont

spécifiques à la représentation si elle font référence aux variables d’instance de l’objet ou

abstraites si elles utilisent une autre approche pour déterminer l’état de l’objet.

• Réflection: la réception d’un message déclenche l’exécution d’une opération dans un méta-

objet. Le méta-objet peut examiner le contenu du message et l’état de l’objet et en conséquen-

ce exécuter l’opération correspondante ou mettre le message dans une file d’attente.

3 Comparaison des Choix de Conception

Afin de comparer les différents choix de conception et leur combinaisons nous avons développé

une série de critères d’évaluation. Ces critères sont basés sur le principe que le langage devrait

rendre aisée la réalisation d’objets qui opéreront correctement en imposant un minimum de res-

trictions sur leur environnement d’utilisation et sur le comportement des objets avec lesquels ils

seront amenés à interagir.

3.1 Critères de Conception

Un langage de programmation à objets offrant une intégration adéquate des concepts de la pro-

grammation par objets et ceux de la programmation concurrente devrait remplir les conditions

suivantes:

1. Protection, exclusion mutuelle: L’intégrité de l’état des objets doit être protégée des ap-

pels concurrent

2. Transparence de l’ordonnancement d’acceptation des requêtes: Il doit être possible

d’ordonnancer l’acceptation des requêtes en utilisant les informations relatives à la re-

quête et à l’état de l’objet. L’ordonnancement des requêtes doit être, dans la mesure du

possible, invisible aux objets clients.

3. Concurrence intra-objet: Il doit être possible d’utiliser la concurrence intra-objet dans la

réalisation des objets afin de permettre l’acceptation de plusieurs requêtes concurrentes

ou de réaliser la fonctionnalité des objets par des algorithmes parallèles. De plus, la con-

currence intra-objet doit être invisible aux clients de l’objet.

4. Transparence de l’ordonnancement d’acceptation des réponses: Il doit être possible de

permettre l’ordonnancement flexible de l’obtention des réponses sans que cela implique

la coopération des objets appelés.

Page 22: Language Design Rationale and Semantic Framework for

Résumé 7

5. Compositionalité, programmation incrémentale: Outre le fait qu’il doit être possible de

développer des objets réutilisables dans différentes applications, les notations utilisées

pour la programmation concurrente doivent pouvoir se combiner avec le mécanisme de

l’héritage et favoriser la programmation incrémentale.

3.2 Evaluation des Choix de Conception

Pour l’évaluation des choix de conception et de leurs combinaisons, effectuée dans le chapitre

4, on se sert d’un exemple d’application concurrente qui nous permet d’identifier et d’illustrer

des situations où certains choix de conception s’avèrent inadéquats par rapport à nos critères.

Procédant ainsi, “par élimination” on arrive à l’identification d’un ensemble des combinaisons

des choix de conception qui satisfont nos critères de conception que l’on présente ci dessous.

Modèles d’Objets

Concernant le modèle d’objets, c’est l’approche homogène qui est la plus satisfaisante. Elle

remplit d’une part la condition (1) en assurant automatiquement la protection de l’état interne

des objets vis à vis des appels concurrents, d’autre part la condition (5) en supportant, au con-

traire de l’approche hétérogène, une seule sorte d’objet pouvant être utilisée dans toutes les ap-

plications.

Mécanismes d’Interaction et Fils de Contrôle

Les conditions (2) et (4) concernant l’ordonnancement des requêtes et des réponses, peuvent être

satisfaites par tous les choix concernant les fils de contrôle pourvu qu’ils soient combinés avec

un choix approprié des mécanismes d’interaction d’objets.

Dans le cas des objets séquentiels, n’ayant qu’un seul fil de contrôle, il est nécessaire d’a-

voir un mécanisme qui permette de retarder l’exécution d’une requête et d’obtenir la réponse aux

requêtes sans suspendre l’exécution du fil de contrôle. La meilleure approche dans ce cas est de

combiner les messages à sens unique avec l’appel de procédure à distance (RPC). Ceci permet

á un objet de tirer avantage dans son implantation des la flexibilite des messages à sens unique

tout en présentant à ses clients une interface RPC. En ce qui concerne l’ordonancement des ré-

ponses il serait aussi envisageable d’utiliser une approche basée sur desproxies, néanmoins il

faudrait un mécanisme permettant de combiner l’ordonancement des requêtes et des réponses,

ce qui fait défaut dans les approches à base de proxies que nous avons examinées.

Dans le cas des objets concurrents et quasi-concurrents, afin de permettre de satisfaire les

conditions (3) et (4) il est nécessaire de combiner le choix de RPC, utilisé comme le mécanisme

principal pour l’inter-action des objets, soit avec la création explicite de fils de contrôle soit avec

Page 23: Language Design Rationale and Semantic Framework for

8 Résumé

des messages à sens unique ou des proxies pour permettre à un fil de contrôle d’émettre des re-

quêtes pouvant être exécutées en parallèle.

Dans le cas d’objets quasi-concurrents, afin de permettre l’ordonnancement des réponses

(4), le blocage d’un fil de contrôle suite à un appel en RPC ou pour l’obtention d’une réponse

par l’intermédiaire d’un proxy, doit entraîner la commutation d’un autre fil de contrôle.

La concurrence intra-objet peut être supportée de manière satisfaisante soit par les objets

concurrents soit par la réalisation de la fonctionalité d’un objet par un ensemble d’objets concur-

rents, pourvu que le choix des mécanismes d’interaction d’objets soit adéquat pour l’ordonann-

cement des requêtes et des réponses et que la sémantique du langage soit telle qu’un objet im-

plantée par un ensemble d’objets concurrents soit substituable dans tout contexte avec un objet

unique offrant la même fonctionalité à ses clients.

Ces deux approches pour la concurrence intra-objet sont complémentaires et il est intéres-

sant de les avoir dans un même langage afin de pouvoir les utiliser dans les situations auxquelles

elles conviennent le mieux. L’approche des objets concurrents rend très facile la réalisation des

objets qui acceptent, en parallèle, plusieurs requêtes qui ne modifient pas l’état de l’objet. La ap-

proche multi-objet est intéressante pour réaliser la fonctionnalité d’une classe d’objets en utili-

sant des objets de classes existantes.

4 Description Sémantique des Langages à Objets Concurrents

Pour la description de la sémantique des langages à objets concurrents nous avons pris l’appro-

che, utilisée par Milner dans [58], qui consiste à spécifier la sémantique d’un langages concur-

rents par “traduction” au calcul des processus CCS. La spécification de la sémantique des lan-

gages de programmation selon cette approche, quoique opérationelle, a une forte ressemblance

aux approches dénotationelles[35][74][78]. La spécification de la sémantique d’un langage de

programmation est donnée comme une fonction faisant correspondre à chaque construction syn-

taxique du langage un terme du calcul des processus, le “sens” des constructions syntaxiques

composées étant défini en faisant appel à celui de ses composantes directes.

Afin de simplifier la description de la sémantique des langages et de permettre de repré-

senter et comparer les divers choix de conception de langages, nous avons établi un ensemble de

conventions pour la représentation des concepts de la programmation par objets concurrents en

CCS, et nous avons défini, en tant que processus parametrisées par des processus, un ensemble

d’opérateurs CCS dérivées permettant de capter directement les concepts de la programmation

concurrente par objets.

Page 24: Language Design Rationale and Semantic Framework for

Résumé 9

Nos choix concernant la représentation des concepts de la programmation par objets en

CCS ont été faits de façon à permettre de décrire facilement et de comparer la sémantique de

langages basés sur des choix de conception différents. Ainsi, l’ensemble de règles de représen-

tation et les définitions d’opérateurs dérivés fournissent un cadre général pour la description sé-

mantique formelle des langages de programmation à objets concurrents. La définition d’un en-

semble de langages nous a permis d’illustrer l’approche pour la représentation d’un grand nom-

bre de concepts de la programmation concurrente par objets comprenant aussi l’héritage dont la

sémantique n’avait pas été spécifiée, auparavant, dans un même cadre que les notations pour la

programmation concurrente afin de permettre d’étude de leur interaction.

Cette approche pour la description sémantique a aussi le bénéfices de pouvoir tirer avantage

du formalisme du calcul de processus CCS afin d’étudier la conception des langages et le com-

portement des objets. Une conséquence importante de ceci, ainsi que du fait que la sémantique

du comportement d’une classe est spécifié par un processus CCS, est qu’on obtient une notion

formelle de comportement et d’équivalence de comportement des objets induite par l’équivalen-

ce des processus CCS correspondants.

5 Conclusion

Afin de pouvoir utiliser la programmation par objets et tirer ses bénéfices pour la construction

d’applications concurrentes, il est essentiel d’une part, d’avoir des langages de programmation

permettant une intégration adéquate des concepts de la programmation concurrente à ceux de la

programmation par objets, et d’autre part, d’avoir des outils formels qui permettent la descrip-

tion rigoureuse de la sémantique de ces langages, et qui fournissent des notions formelles du

comportement et de la compatibilité du comportement des objets.

Concernant la conception des langages de programmation à objets concurrents, nous avons

étudié l’interaction des concepts de la programmation par objets et de la programmation concur-

rente et produit un cadre conceptuel permettant d’évaluer les choix de conception des langages.

En utilisant ce cadre on a identifié un ensemble de combinaisons de choix de conception pour

les langages à objets concurrents offrant une intégration adéquate de ces concepts.

Pour la description de la sémantique des langages à objets concurrents nous avons produit

une formalisation des concepts de la programmation à objets concurrents dans le calcul de pro-

cessus CCS permettant la description formelle des divers choix de conception et qui a permis

d’ obtenir des notion formelle, essentielles en vue de leur réutilisation, du comportement et de

compatibilité de comportement des objets concurrents.

Page 25: Language Design Rationale and Semantic Framework for
Page 26: Language Design Rationale and Semantic Framework for

CHAPTER 1

Intr oduction

Object-Oriented (OO) programming [25][34][56][64] has become extremely popular for the de-

sign and construction of software systems. It is a programming approach that advocates the con-

struction of systems structured as a collection of interacting software objects that reflect their

application domain counterparts. It also provides a framework that encompasses a host of pro-

gramming techniques such as modularity, encapsulation, data abstraction, polymorphism and in-

heritance that are useful for the construction and maintenance of software and that promote soft-

ware reusability[12]. The full deployment of OO techniques and their potential for software re-

usability[57][82] is best achieved on one hand by the use of object-oriented programming

languages (OOPL) which directly support the object-oriented concepts and on the other by de-

sign methods [30][40][89], techniques and tools [33] that aim at larger-scale reuse and assist the

construction and dissemination of reusable software.

The motivation of this work is to take advantage of object-oriented programming tech-

niques and their potential for software reusability for the construction of concurrent software

systems. There are two important issues to consider for approaching this goal. The first is the

design of Concurrent Object-Oriented Programming Languages (COOPLs) that integrate the

object-oriented techniques with concurrent programming. The second is the development of se-

mantic models that provide a rigorous basis for the design and development of concurrent sys-

tems following an object-oriented approach.

The problem that is posed by the design of COOPLs is that issues of concurrency, contrary

to what one might naively expect, are not orthogonal to object-oriented concepts. The interfer-

ence of the concurrency and object-oriented features makes it hard to achieve their satisfactory

integration.

Page 27: Language Design Rationale and Semantic Framework for

Object-Oriented Programming12

The development of semantic models for the description of the semantics of concurrent ob-

ject-oriented features is important both for analyzing the various language features and for the

rigorous description of the behavior of active objects. A rigorous way to describe the behavior

of active objects independently of particular implementations is crucial in order to be able to re-

use objects across applications.

In section 1.1 we review the main concepts underlying object-oriented programming and

the benefits entailed by following an OO approach for software development. The purpose of

this section is to provide some background on object-oriented programming and set up the stage

for presenting in 1.2 and 1.3 the problems addressed by this work. Namely, the designof

COOPLs and the development of models for the semantic description of OO languages and sys-

tems.

1.1 Object-Oriented Programming

Object-oriented programming is a programming approach that views software systems as col-

lections of objects interacting by exchanging messages. Central to the approach are the concepts

of object and message.

Objects and Messages

An object is an identifiable entity, usually modelling an application domain counterpart, that

supports a number of operations. The set of supported operations, also called methods, consti-

tutes the object’s interface and determines what one can do with the object, e.g. use a service

provided by it, find out about or modify the state of the application domain entity modelled by

the object. To invoke an object’s operation one sends a message requesting it to execute its op-

eration and, eventually, return a result.

The message metaphor is used to emphasize that the caller has no control over the exact

actions that are performed at the receiver object. This is realized by the means ofdelayed binding

where the code executed is determined not only by the requested operation but also by the way

that the operation is implemented by the receiver.

The state of an object persists during its entire lifetime and is maintained in the object’sin-

stance variables. The scope of instance variables is confined to the object’s operations so that

updates or inquiries concerning the object’s state may only take place indirectly by invoking an

appropriate operation. Thisencapsulation of the object’s state and operations has several bene-

fits:

Page 28: Language Design Rationale and Semantic Framework for

Chapter 1 13

• It enhances modularity [70][71] by establishing and enforcing well defined boundaries

between objects at the operation interface. Furthermore, the modular decomposition of a

system is in terms of objects that represent entities of the application domain. This pro-

duces modular units that are more likely to be reused across application than modules

that occur from the decomposition of an application’s functionality for managerial pur-

poses.

• It provides support fordata abstraction [49] by insulating the programs that use objects

from the way that objects are implemented and protecting the integrity of the object state.

Data abstraction supports programming at a higher level of abstraction and the possibil-

ity to modify or extend the implementation of objects without affecting already devel-

oped programs that used them.

Classes and Class Inheritance

Classes specify the structure of objects and the implementation of their operations and act as

templates for the creation of instances of the class.

Class inheritance is a mechanism that may be used for the incremental definition of a class

in terms of some already defined classes that are called itssuperclasses or parent classes. The

newly defined class is called a subclass of its superclasses. If no more than one parent class may

be used in defining the class then the inheritance mechanism is called single inheritance and

multiple inheritance otherwise.

Class inheritance allows class definitions to be reused in the definition of new classes and

has been considered as a criterion to characterize a language as object-oriented [87]. However,

it has been a source of problems because of the way that it has been included in some program-

ming languages. As discussed by Snyder in [75] the encapsulation of objects, which is an essen-

tial feature of object-oriented programming, is violated by the inheritance mechanism of some

languages. Other problems are, as will see in the next section, caused by using the class inherit-

ance hierarchy for defining the type systems of some object-oriented languages and, as we dis-

cuss in section 1.2, its interference with the concurrency mechanisms in the case of COOPLs.

Substitutability, Types, Subtypes and Polymorphism

Late binding makes it possible to write programs that operate on objects of any class provided

that the operations required by the programs are supported by the class and that the behaviors

provided by the classes are compatible in some sense. This idea is known as the principle ofsub-

Page 29: Language Design Rationale and Semantic Framework for

Object-Oriented Programming14

stitutability. Any object may be used in a program context for which it supports the required op-

erations and behavior independently of the way it is implemented.

With untyped object-oriented languages any object may be used in any program context

and it is the responsibility of the programmer to prevent run-time errors by ensuring that objects

satisfy the requirements of substitutability. Typed object-oriented languages assist the program-

mer through compile time type-checking to ensure, to some extent, that objects satisfy the sub-

stitutability requirements.

Unlike classes which provide the information necessary for the creation of their instances,

types are motivated by compile time type-checking and express constraints on the objects usable

in some program context. Depending on the notion of types supported, object-oriented languag-

es express different notions of object compatibility that vary in their ability and flexibility to cap-

ture substitutability. Several such notions of compatibility are discussed by Wegner and Zdonik

in [88] for examining various forms of incremental modification supported in object-oriented

languages. Two of these aresignature compatibility andbehavior compatibility.

Signature compatibility is based on the signature of operations applicable to the objects of

the type and is behind most notions of object-oriented types. Type-checking based on signature

compatibility will ensure that objects support all the operations, with the appropriate number of

arguments and compatible argument types, that are required in some program context.

Behavior compatibility is a semantic notion and it can be expressed by associating an alge-

bra with the signature of the type [88] or axiomatically[6][37] by associating operations with

preconditions and postconditions on some abstract representation of the states of the objects of

the type.

A type system ispolymorphic[26] if objects may satisfy the constraints required by more

than one type specification. In such a type system a type S is called asubtype of a type T if every

object that qualifies as an object of type S also qualifies as an object of type T. Polymorphic type

systems are very important for object-oriented programming. They can be used for making sure

at compile time that the requested operations are effectively supported by the invoked object

without imposing any further constraint on the object’s class.

In practice the approaches that have been followed by strongly typed object-oriented lan-

guages are the following:

• Collapse the notion of type with that of a class and use the class-subclass relationship as

a subtype relationship.

Page 30: Language Design Rationale and Semantic Framework for

Chapter 1 15

• Specify types in terms of the signatures of the supported operations and use some notion

of signature compatibility motivated by substitutability to specify type compatibility and

subtypes.

• Use some form of signature compatibility augmented by some means to specify more

about the semantics of the type. This is done to allow the programmer to associate more

semantic information with signatures to prevent cases where the signatures of different

object classes are accidentally compatible. This approach is illustrated by POOL-I[7].

The approach that identifies types with classes and subtyping with inheritance makes type-

checking easy but has drawbacks. It unduly restricts substitutability and constrains the use of

class inheritance. There may be classes that are not in a class-subclass relationship that are sig-

nature and behaviorally compatible, however, instances of such classes are not interchangeable.

With respect to the use of class inheritance for code reuse, the substitutability principle requires

subclasses to inherit and provide to their clients all the superclass’s methods although just some

may be useful for defining the subclass.

Type systems incorporating the notions of types discussed, their use in object-oriented lan-

guages and their underlying theory are presented in [20]and [26]. Wegner and Zdonik in [88]

discuss the relation between types, classes, inheritance and subtyping. Some of the drawbacks

of identifying subtyping and inheritance in a language are discussed in [41].

1.2 Designing Concurrent Object-Oriented Languages

To make use of object-oriented techniques for constructing concurrent applications it is neces-

sary to provide a way to express concurrent execution and synchronization in a object-oriented

language. This may be accomplished by using a variety of concurrent programming nota-

tions[9]. Furthermore, there are various ways in which these notations have been, or may be,

combined with OO constructs in COOPLs[69].

However, arbitrary combinations of concurrency and object-oriented features may not pro-

duce the desired effect. Issues of concurrency are not orthogonal to object-oriented ones and, as

has been noticed recently by a number of researchers [17][41][68][80], the interference of con-

currency and object-oriented features defeats the purpose of object-oriented techniques for the

development of concurrent software.

A first approach that may come to one’s mind for the design of a COOPL is to introduce in

a object-oriented language the notion of concurrent process and some mechanism for process in-

teraction independently of objects. With this approach there are two independent concepts: con-

Page 31: Language Design Rationale and Semantic Framework for

Designing Concurrent Object-Oriented Languages16

current processes and objects, in terms of which applications may be structured. The disadvan-

tage of such an approach is that it weakens modularity. The boundaries of the system compo-

nents produced from applying each concept independently may intersect so that neither of the

two structuring concepts may produce self-contained modular units. As the process communi-

cation-synchronization boundary may be different from the object interface, objects cannot be

implemented independently from the process structure of an application. For instance, objects

should be implemented differently according to whether they are used in a program where they

will be shared by concurrent processes. Shared objects should be implemented in such a way that

their internal state is protected from the concurrent invocation of their methods.

A second approach is to integrate the concepts of object and process into the concept of ac-

tive object having its own single thread of control. This has the benefit that there is a single con-

cept for structuring applications and shows better modularity. However, it restricts the number

of threads that can be used to implement objects and it may thus weaken the power of data ab-

straction when multiple threads are needed for the object’s implementation. In principle it would

be possible to use objects to represent internal control threads, however as we will see depending

on the features supported by a language this approach for the implementation of objects may not

always be hidden behind an object’s interface and weakens thus the support for data abstraction.

Another aspect to consider in the design of the concurrency constructs and their integration

with object-oriented features is the use of class inheritance. Depending on the design of the con-

currency constructs of the language class inheritance may be useless because all inherited meth-

ods may have to be rewritten. In other cases, in order to properly synchronize the execution of

methods defined in a subclass with inherited methods, subclasses have to access the instance

variables of their superclass, thus violating encapsulation. In some approaches it is attempted to

separate the concurrency constructs from the code of the methods so that inheritance may still

be used for the “sequential” part of the object. Yet, in other approaches it is attempted to specify

independently, reuse and specialize the specification of synchronization policies for the execu-

tion of methods.

In order to develop languages that achieve a graceful integration of concurrency with ob-

ject-oriented features it is essential to have a deeper understanding of the interaction of the issues

of concurrency with the object-oriented concepts and to develop criteria for establishing their

integration. The various language design approaches may then be compared by their impact on

the integration of concurrent programming with object-oriented techniques in several aspects of

language design.

Page 32: Language Design Rationale and Semantic Framework for

Chapter 1 17

An approach that may be followed for evaluating whether the different design choices pro-

vide satisfactory support for object-oriented programming is to construct examples that show

that the features under examination fail to support object-oriented techniques. With this ap-

proach we are able to identify constructs and combinations of constructs that are inadequate for

concurrent object-oriented programming. However, this approach for evaluating languages re-

quires to construct appropriate examples and uses of the language that reveal the interference of

features or their inadequate support for object-oriented techniques in various aspects of the lan-

guage design. This in some cases may only be possible after a language has been designed and

implemented. The development of a semantic framework for COOPL, discussed in the next sec-

tion, will be useful for providing a more rigorous approach for examining the interaction of fea-

tures and representing and comparing the various design alternatives.

1.3 Specifying the Semantics of Active Objects

Apart from the fact that the semantic description of COOPLs, and object-oriented features more

generally, is an interesting problem in its own right, several practical benefits, discussed below,

are to be drawn from a semantic model for describing the behavior of active objects.

Semantic descriptions of COOPLs have been scarce. Furthermore, the following important

issues underlying the semantics of concurrent object-oriented programming have been ad-

dressed, if at all, to a limited extent:

• The description of the semantics of the full range of object-oriented features so that it is

possible to examine their interaction in a formal setting. For instance inheritance has not

been taken into account in previous semantic descriptions of COOPLs.

• A framework in which the different design approaches taken by COOPLs may be cap-

tured and compared. Most semantic descriptions have concentrated on a particular lan-

guage and it is not clear whether and how languages based on different design approach-

es may be accommodated within the same semantic framework.

• The semantics should assign meanings to individual objects rather than complete pro-

grams. Moreover, the meaning assigned to objects should be useful as a notion of behav-

ior that abstracts from their implementation and should allow various notions of behav-

ioral compatibility among objects to be developed.

The last point is extremely important for taking advantage of object-oriented techniques for

developing concurrent systems. In order to reuse objects, take advantage of principle of substi-

Page 33: Language Design Rationale and Semantic Framework for

Contributions18

tutability and describe behavioral dependencies among components of application frameworks

a clear notion of object behavior is needed.

The approach that we have taken for the semantic description of COOPLs which fully ad-

dresses the first two points assigns as the meanings of individual objects terms of the Calculus

of Communicating Systems (CCS)[58]. This allows us to use all the underlying formal frame-

work for discussing the issues of behavior compatibility, substitutability and expressing and ver-

ifying behavioral constraints for objects.

1.4 Contributions

The main contributions of this thesis are: (1) A conceptual framework for understanding the in-

teractions of concurrency and object-oriented features and for comparing language design choic-

es with respect to the integration of concurrency and object-oriented programming; (2) A formal

framework for describing the semantics of a wide range of COOPLs and for providing a rigorous

notion of behavior for active objects. The points below summarize the specific elements of these

contributions.

• A case study of the integration of concurrency and object-oriented features in the language

Hybrid that concretely shows the effect of language design choices in integrating concurrent

and object-oriented programming. It identifies both choices that are problematic because of

the interference between features as well as choices that achieve a successful integration of

concurrency and object-oriented concepts.

• A design space for COOPLs that captures the different approaches for the combination of con-

currency and object-oriented features.

• A set of requirements for evaluating the support provided by COOPLs for object-oriented pro-

gramming and for comparing the different design approaches.

• A set of guidelines for the combination of design choices that successfully address the above

requirements.

• The development of a formal framework for describing the semantics of COOPLs that:

• Captures the standard OO features and concurrency and the different language design ap-

proaches.

• Models the semantics of individual object classes by CCS agents providing thus a rigor-

ous notion of object behavior and behavior equivalence induced from agent equivalence.

Page 34: Language Design Rationale and Semantic Framework for

Chapter 1 19

• Makes possible to use the underlying CCS theoretical framework to reason about the be-

havior of objects.

1.5 Thesis Overview

Chapter 2 discusses in more detail the difficulties of integrating concurrency and object-oriented

programming. The discussion is carried out with respect to a particular language, Hybrid[62],

and is based on our own experience gained through our participation in the design and imple-

mentation of a prototype for this language[42][68].

In chapter 3 , in order to understand what are the different ways for combining concurrency

and OO features, we develop a design space capturing the essentially different approaches for

the design of COOPLs with respect to three separate aspects of language design. We then survey

a number of existing languages and state where they are situated in this design space.

Chapter 4 presents a list of requirements for the design of COOPLs to achieve a successful

integration of concurrency and object-oriented programming. Then, we explore the design space

presented in chapter 3 and examine how these requirements are addressed by the various design

choices. A number of examples and re-use scenarios are used for identifying the inadequacy of

certain design choices from an OO programming point of view.

Chapter 5 addresses the problem of the formal description of the semantics of object behav-

iors and the semantics of COOPLs. We take the approach of giving the semantics of objects by

translation to terms of a process calculus. We propose a framework, based on CCS[58], for such

a semantics and show how the different design choices discussed in chapter 3 can be accommo-

dated.

In chapter 6 we discuss a number of promising directions for future research. These include

the development of behaviorally motivated conformance relations for objects, further use of the

framework discussed in chapter 6 to more rigorously compare language and application designs

with respect to their re-use potential.

Page 35: Language Design Rationale and Semantic Framework for
Page 36: Language Design Rationale and Semantic Framework for

CHAPTER 2

Issues in the Design andImplementation of the ConcurrentObject-Oriented Language Hybrid

Hybrid is a concurrent object-oriented language and runtime system that was developed at the

University of Geneva. The aim of the project was to integrate the basic object-oriented concepts

of encapsulation, data abstraction and inheritance with strong typing, concurrency, persistence

and distributed execution. The integration of all these features in a single system was innovative

as, to our knowledge, there was no other language/system which had achieved a similar goal,

and still the clean integration of some of these features remains an open problem. The original

language design was presented in [62] and the design and implementation of a prototype, includ-

ing a substantial subset of the projected features, is described in [42].

The implementation of the prototype uncovered difficulties in the integration of several

features as well as semantic flaws in the original language design[62][63]. Thus, the language

has undergone some changes in order to patch these flaws, and some features, whose integration

deserved more examination, were left out to make the implementation easier. The examples and

further discussion on Hybrid, unless explicitly stated, are about the implemented language pro-

totype [42].

The experience that was gained through the development of the prototype and the further

study of the design of Hybrid by us [68] as well as by other researchers [41][80] brought out

several issues concerning the integration of object-oriented concepts with other features and

concurrency in particular.

Page 37: Language Design Rationale and Semantic Framework for

Overview of Hybrid22

In this chapter, using Hybrid as a concrete example, we discuss several issues concerning

the design and implementation of concurrent object-oriented languages. We start with a short

overview of the Hybrid language that provides the necessary background for understanding the

issues discussed in later sections. Then we present the concurrency features and their implemen-

tation and discuss their integration with object-oriented features. We conclude by summarizing

the general issues in the design of COOPLs, revealed through our experience with Hybrid, con-

cerning the successful application of object-oriented techniques for the construction of concur-

rent software.

2.1 Overview of Hybrid

Hybrid is a strongly typed language which, by abstract typing, subtyping and dynamic binding,

combines most of the advantages of static (compile time) type checking with the flexibility of

non statically typed languages as Smalltalk[34].

Object Types

The language constructs for type definition include a number of predefined object types such as

integers and booleans, more conventional type constructors such as structures and enumerated

types, and anabstract construct that supports the definition of abstract data types. The use of the

abstract type constructor is shown below in the definition of a stack of integers.

type integerStack:

abstract{

push: integer ->;

pop: -> integer;

empty: -> Boolean;

full: -> Boolean;

}

private{

instance variables

var buffer: array[1..100] of integer;

var top:= 0: integer;

implementation of the operations

empty(): -> Boolean;

{ return( top =? 0); }

full(): -> Boolean;

{ return( top =? 100); }

...more operation implementations ...}

Page 38: Language Design Rationale and Semantic Framework for

Chapter 2 23

All objects are typed. We distinguish between theeffective andactual type of objects. The

effective type determines the operations that are supported and that determine the object’s inter-

face. The actual type of an object determines the representation of its internal state and the im-

plementation of its operations.

Type equivalence is defined as structural equivalence[2] on the effective object types. Two

types are equivalent if their instances support the same number of operations which have the

same names and number of arguments, and the types of arguments and return types are equiva-

lent. Predefined types such as integer and character, provide the base case in this recursive def-

inition. A conformance relation on types is defined as follows: A typeS conforms to a typeT if

for every operation supported byT, S supports an operation with the same name and the types

of arguments and return values are of equivalent types.

Type checking is based on the conformance relation over the effective types of objects and

determines, at compile time, whether the types of expressions conform to the type required by

the context where they appear. This ensures that the invoked operations are effectively defined

at the interface of invoked objects.

This approach to typing and conformance accounts for polymorphism [20] in the Hybrid

type system and supports the construction of programs which operate on refined versions of con-

forming types yet to be defined. It is important to note that unlike other typed object-oriented

languages, such as C++ [76] and Eiffel [54] where conformance requires that an inheritance link

exists between conforming types, the typing issues are kept separate from inheritance as in

POOL-I[7].

Hybrid also supports the definition of parametrized types and provides the possibility to

constrain the type parameters to be equivalent or conform to some existing type.

Object Interaction and Concurrency

Objects in Hybrid are active entities that interact by invoking one another’s operations in a re-

mote procedure call fashion. An object sends acall message to another, requesting it to execute

one of its methods, and then waits until the results are returned by areturn message. Arguments

to operation invocations are passed by value. This decision was made in order to support distrib-

uted execution and to provide more control on the use of an object’s subobjects (objects stored

in its instance variables) by not allowing them to be referenced by other objects. Object sharing

and a form of argument passing by “reference” is supported by explicit use ofoidswhich are

objects holding references to other objects.

Page 39: Language Design Rationale and Semantic Framework for

Overview of Hybrid24

The thread of nested remote procedure calls amongst a set of objects is called anactivity.

An activity is created by invoking an operation defined as areflex.The invocation of a reflex

takes place by sending astart message after which the sender proceeds in parallel with the re-

ceiver.

A collection of objects consisting of a “top-level” object and its subobjects is called ado-

main. When an object is created it is possible to specify whether the new object is in the domain

of its creator or if it is created as an independent top-level object. A domain is the unit of paral-

lelism and it may be in one of the three states:active, blocked or idle. It is active when an object

is executing an operation in response to a call or start message. It is blocked when it has invoked

the operation of another object and waits for the reply. It is idle if it is neither active nor blocked.

An object in a idle domain may accept any kind of message1 from any activity. Objects in

a blocked domain may accept return as well as call messages associated with the corresponding

activity. The possibility of accepting further call messages associated with the activity on which

the domain is blocked supports a form of “recursive” call allowing an object to call itself or its

caller without causing a deadlock.

Apart from the above rules, acceptance of call messages may be controlled in a program-

mer-defined way by thedelay queue mechanism. Delay queues are defined as instance variables

of typedelay. They may beopen orclosed and may be associated with the operations of the ob-

ject. The acceptance of call messages for an operation associated with a closed delay queue is

delayed until the delay queue is open.

Thedelegated call mechanism, explained shortly, allows an object to call an other object

without becoming blocked. A delegated call causes the domain of the calling object to become

idle. Thus, the caller or other objects in the domain may switch their attention to other activities.

This feature is made possible by supporting multiple threads within objects which execute in a

quasi-concurrent fashion.

The synchronization provided by domains and activities is very useful for computations in-

volving the coordinated execution of a collection of objects. The correctness of such a compu-

tation is based on implicit assertions on the states of participating objects. The concurrent exe-

cution of objects may cause state changes that invalidate such assertions. Domains and activities

provide the possibility to coordinate the execution of objects so that no interference may occur

by their concurrent execution.

1. it is possible for an idle object to receive a return message because of the delegated call mechanism ex-

plained next.

Page 40: Language Design Rationale and Semantic Framework for

Chapter 2 25

For example, a bank account class,Account, supports, among others, operations for reading

its balance, and withdrawing and depositing an amount. ATeller class is used to provide restrict-

ed access to bank account operations. This class supports operations for reading an account’s

balance and withdrawing an amount under a certain limit. When a withdrawal is requested to an

instance of this class it checks that the requested amount does not exceed this fixed limit and that

sufficient funds are available in the associated bank account. It then carries out the withdrawal

by invoking the bank account’s withdraw operation.

If Teller instances and their associated accounts are independent objects the concurrent ex-

ecution of teller objects sharing an account may interfere causing the account to be overdrawn.

This situation is illustrated in figure 2.1-1 where twoTeller instances and a shared account are

shown as independent objects. The concurrent execution of requests by teller objects may take

place as follows: Both tellerobjects accept withdrawal requests at (1), (2) for amounts not ex-

ceeding the fixed limit. Then both check at (1.1) and (2.1) whether the requested amount does

not exceed the account’s balance and then proceed with the withdrawal at (1.2) and (2.2). How-

ever, if the sum of the requested amounts exceeded the account’s balance the account would be

overdrawn.

This problem, as other such problems, may be solved by having theTeller instances and the

associated account be in the same domain. As illustrated in figure 2.1-2, once a withdrawal re-

quest is accepted by one object, say Teller1, requests from other activities are delayed at the do-

(1.1)

(2.1)

(1.2)

AccountTeller1

Teller2

1

call message

completed rpc

object boundary

domain boundary

Withdraw1

Withdraw2

(2.2)

(1.1)(1.2)

Teller1

2

Withdraw1

Withdraw2

Account

Teller2(1)

(2)

Figure 2.1

Page 41: Language Design Rationale and Semantic Framework for

The Concurrency Features26

main boundary. This is an elegant solution to this problem which allows the different access

views to accounts to be represented as separate objects classes. Moreover, no extra programming

effort is required in the implementation of theTeller andAccount classes for synchronizing the

execution of their instances.

2.2 The Concurrency Features

Hybrid includes high level constructs that directly support object interactions according to the

message passing model that was presented in the previous section. As remote procedure calls are

the primary means for expressing object interaction, the language classifies as anoperation ori-

ented language in the concurrent programming language classification of Andrews and Schnei-

der [9].

In order to motivate the presentation of the concurrency constructs of Hybrid we are going

to use the concurrency requirements of Liskov et al.[49] for the construction of distributed pro-

grams. These programs are considered to be structured as a collection of active modules acting

as servers and clients, a structure that closely matches object-oriented programs.

The main requirement formulated in [49] is that when an activity becomes blocked within

a module (object in the case of Hybrid) other activities should be able to proceed. They identify

two common situations where an activity may get blocked:local delayandremote delay.

Local delay is the situation where an object is unable to service a request because of the

temporary unavailability of a local resource. In such a case, the object should be able to set aside

this request and turn its attention to others. Moreover, not being able to set aside a request that

cannot be processed immediately may also cause unnecessary deadlocks; while being blocked

because of the unavailability of a local resource, the object would be unable to accept requests

that would made the resource available. For instance, a full bounded buffer object should be able

to accept requests for removing items in order to get to a state where further requests to insert

items can be processed.

Remote delay is the situation in which an activity is delayed within an object because of a

call to another object acting as a “lower level” server. The delay may be due to the communica-

tion delay, the time needed by the lower level server for handling the request or a local delay in

the lower level server. During this time further requests could be accepted and processed by the

object.

Page 42: Language Design Rationale and Semantic Framework for

Chapter 2 27

2.2.1 Local Delays With Delay Queues

In Hybrid, simple forms of local delay are handled easily with delay queues. The use of delay

queues allows objects to avoid accepting a request that would lead to a local delay. An illustra-

tion of the use of delay queues for simple cases of local delays is given below by the code outline

of a bounded buffer.

type boundedBuffer : abstract {init : ->;put : string ->; uses delay;get : -> string; uses delay;

};private {

var putDelay, getDelay: delay;var buffer: strarray;...init: ->;{

...putDelay.open();getDelay.close();

}

get: -> string; uses getDelay;{

...get an item.if the buffer is now empty

getDelay.close();putDelay.open();...

}

put: string ->; uses putDelay;{

...insert an itemif the buffer is now full

putDelay.close();getDelay.open();

}}

The delay queuesgetDelay andputDelay are used for avoiding the acceptance ofget andput

requests when the buffer is empty and full respectively. Initially the delay queuegetDelay is

closed so that noget requests are accepted and the delayputDelay is open so thatput requests are

accepted and items may be inserted in the buffer. When the methodput is executed it opens the

delay queuegetDelay so thatget requests may be accepted. The method get determines whether

the buffer is empty and then closes thegetDelay delay queue. The methodput closes theputDelay

delay queue when the buffer is full.

Page 43: Language Design Rationale and Semantic Framework for

The Concurrency Features28

In the above example, whether a request will lead to a local delay is determined by the re-

quested method and the local state of the object. However, there are cases where this information

is not sufficient and it is also necessary to know the values of the method’s arguments[15]. Such

cases are dealt with in Hybrid by combining delay queues with the delegated call mechanism. In

section 2.2.3, after we have introduced the delegated call mechanism, we will show how to han-

dle more complex cases by a combination of delay queues and delegated calls.

2.2.2 Remote Delays With Delegated Calls

The delegated call mechanism is well suited for remote delays. When an object issues a delegat-

ed call the executing thread is suspended. Another request may then be processed by another

thread. A thread that was suspended because of a delegated call is resumed after the delegated

call returns and there are no other active threads within the object.

As an example illustrating the use of the delegated call mechanism, consider an object that

operates as an administrator for a collection of worker objects. This object is acquainted with a

collection of worker objects that it uses for servicing the requests made by clients. Remote de-

lays occur when the administrator invokes a particular worker for doing the job. It would not

make sense for the administrator to wait until the worker finishes the requested work. Instead, it

should accept other requests and pass them on to other workers that would process them in par-

allel. The use of the delegated call mechanism allows the administrator to switch its attention to

another request while a call is passed on to a worker. The outline of the administrator is given

below.

type administrator: abstract {doWork(work: WorkType)-> resultType;

} ;private{

var workers: array[1..MAX] of oid of workerType;doWork(work: WorkType) -> resultType{

var workerIndex: integer;var result : resultType;

select the worker appropriate for this work,assign its index to workerIndex.Pass on the request to the worker by issuing a delegated call

result <- delegate(@workers[workerIndex].doIt(work));

gather some statistics about workers based on resultreturn the result to the caller.

Page 44: Language Design Rationale and Semantic Framework for

Chapter 2 29

return(result);

}

}

Thedelegate(...) expression causes the executing thread to be suspended and the call mes-

sage to be passed on to the selected worker. While the worker handles the call, another call may

be accepted by the administrator. This call is handled by the implicit creation of a new thread.

However, there may not be more than one active thread at a time within an object. Suspended

threads are resumed after the delegated call has returned and there are no other active threads

within the object.

2.2.3 Using Delegated Calls and Delay Queues for Local Delays

In section 2.2.1 we mentioned that some local delays that cannot be handled by delay queues

alone can be handled by combining delay queues and delegated calls.

In order to suspend the execution of one of its methods, an object may issue a delegated call

to another object. The delegated call causes the invoking thread to be suspended and the object

is free to accept further requests. If the method invoked by the delegated call is associated with

a closed delay queue, the suspended thread in the calling object is delayed until the execution of

another method opens the delay queue. This causes the call to be accepted so that the delegated

call may return.

A typical object, used for suspending the execution of another object’s methods, would pro-

vide two methods:suspend andresume implemented as follows:

private{

var suspendDelay: Delay;

This delay is initially closed so that callers are delayed

suspend():->; uses suspendDelay;

{

Close the delay so that the next caller will be suspendedsuspendDelay.close();

}

resume(): ->;

{

suspendDelay.open();

}

}

The delay queuesuspendDelay is initially closed. An object willing to suspend the execu-

tion of one of its methods issues a delegated call of the form:delegate(@secondObject.suspend()).

Page 45: Language Design Rationale and Semantic Framework for

An Implementation of The Hybrid Concurrency Model30

This suspends the calling activity until a call toresume opens the delay queue. Assuspend is

called by a delegated call the calling object is free to accept further calls before the call to sus-

pend returns. A call toresume opens the delay queue and so that the call tosuspend may be pro-

cessed and the invoking thread resumed. The resumed thread closes the delay queue so that the

next call tosuspend will also be delayed. This example assumes thatresume is called only when

there is a delayed call. If not, the delay queue would remain open and the next call tosuspend

would not be delayed.

2.3 An Implementation of The Hybrid Concurrency Model

For the implementation of the Hybrid prototype [42] we developed,on top of Unix, a runtime

environment to better support the needs of the system. This runtime environment which provides

support for concurrency, persistence and communication with the outside world is implemented

as a single Unix process. Concurrency is supported by a “custom made” package for lightweight

processes which share the address space of this Unix process. Persistence is provided as in the

Smalltalk-80 system by saving the workspace of active objects to a file. The size of the work-

space is limited to the size of virtual memory. Communication to the outside world is provided

by an i/o package based on Unix sockets. This i/o package is integrated with the lightweight

package in the sense that i/o requests block only the requesting lightweight process and multiple

“virtual” connections are supported over a single socket.

Figure 2.2 shows the system’s architecture. The basic system components are the work-

space manager, the type manager and the activity-domain manager. The workspace manager

maintains a persistent workspace for storing objects. The type manager maintains information

about object types. The activity-domain manager keeps track of the state of execution of Hybrid

domains and activities.

The Hybrid compiler translates object type definitions to C code that uses the functionality

of the runtime environment. The compiler interacts with the type manager for finding out infor-

mation about existing types and for storing information about new types. The generated C code

includes calls to functions that provide the interface to the basic system components of the runt-

ime environment. Thus, Hybrid objects, by being translated into C, are integrated and use the

services of the runtime environment.

A limitation of the current implementation is that it is not possible to compile and integrate

new classes to the system while it is running. This could be made possible by a dynamic linking

Page 46: Language Design Rationale and Semantic Framework for

Chapter 2 31

facility that would allow the C code produced by the Hybrid compiler to be read in and dynam-

ically linked with the runtime environment.

Multiple users may interact with the system, as shown in figure 2.3, through processes that

connect as clients to the runtime environment process which acts as a Hybrid server. Client pro-

cesses are responsible for implementing user interaction objects, such as windows, for which

shadow versions exist in the runtime environment..

In the following sections we are going to describe how the message-passing concurrency

model of Hybrid was implemented in the “shared memory” runtime environment described

above. A more detailed presentation of the prototype implementation may be found in [42].

Figure 2.2 System architecture

Runtime Environment

I/OLibrary

LightWeightProcesses

PersistentWorkspace

Activity/

Manager

PredefinedObjectLibrary

TypeManager

WorkspaceManagerDomain

Basic System Components

Hybrid Objects

Runtime Library Hybrid Compiler

SystemObjects

Figure 2.3 Multi-user support

HybridObjects

SystemDefinedObjects

I/OLibrary

User InteractionObjects

I/O Library

User InteractionObjects

I/O Library

Client Process Hybrid Server Client Process

Socket Socket

Page 47: Language Design Rationale and Semantic Framework for

An Implementation of The Hybrid Concurrency Model32

2.3.1 Implementing the Concurrency Model

Although in Hybrid all objects are considered as active entities that resemble processes that in-

teract by exchanging messages, they are implemented as passive data types whose operations

are invoked by the lightweight processes of the runtime environment. The execution of the ob-

ject’s operations by the lightweight processes is appropriately synchronized so as to reproduce

the semantics of Hybrid’s model of active objects.

We found this approach for the implementation of Hybrid to be natural as:

• The runtime environment that we built for supporting the language provided a shared

memory architecture, i.e. lightweight processes sharing the address space of a Unix pro-

cess.

• Operation oriented languages like Hybrid, which use remote procedure call as their main

object interaction mechanism can be implemented efficiently as a procedure oriented

language in a shared memory environment[9].

Another approach to the implementation of the prototype would have been to use Unix processes

to support concurrency and build a run time environment based on a “distributed architecture,”

that is the logically distributed address spaces of Unix1 processes communicating through sock-

ets. This, however, would not eliminate the need to support concurrency within a Unix process

as delegated calls require quasi-concurrent execution within Hybrid objects. Moreover, it would

force us to resolve issues concerning the distributed execution of Hybrid which we did not want

to consider for the implementation of the prototype.

2.3.2 Efficiently Supporting the Active View of Objects

The run-time overhead induced by the active view of objects in the above implementation is due

to the synchronization of method execution. As objects of any type may be invoked concurrently

it may seem that synchronization code has to be generated in the methods of all objects to control

their concurrent invocation. In fact, the synchronization takes place when objects are invoked,

rather than by code generated within methods. The use of different kinds of references for ob-

jects makes it possible to synchronize only the invocations of objects whose methods may be

invoked concurrently.

The predefined object type,oid, is used for specifying a reference to an object. Oids may be

passed around to other objects so that the methods of an object having an oid may be invoked

1. The implementation platform was a 3.2 Sun operating system; a 4.3BSD based system which did not

provide lightweight processes or shared memory facilities. The main ipc mechanism provided was sockets.

Page 48: Language Design Rationale and Semantic Framework for

Chapter 2 33

concurrently. On the other hand, objects that are addressed by instance variable names are local

to the enclosing object and are not known to other objects so their methods may not be invoked

concurrently. As objects that are addressed by instance variable names may not be addressed by

oids and conversely, only invocations through oids need to be synchronized.

The use of the type oid is illustrated below in the definition of a typeA with a method

anAMethod. Instances of this type have two instance variables, local andshared, for referencing

two objects of a typeB. The object stored inlocal may only be addressed through this name and

thus it may not be known outside the scope of the containing object of typeA. Variableshared

stores an oid that is used to refer to another object of typeB. The oid may be known to other

objects, consequently invocations of objects addressed by oids, [email protected], are syn-

chronized. No synchronization occurs when invoking methods of objects that are addressed by

local names, as inlocal.aBMethod().

type A: abstract {

anAMethod: ->;

} ;

private{

var local: B;var shared: oid of B;

anAMethod: -> ;

{

...local.aBMethod(); @shared.aBMethod(); ..

}

}

2.4 The Integration of the Concurrency and Object-Oriented Features

In the preceding sections we have presented how object-oriented and concurrency features have

been combined in Hybrid. We have also discussed and shown that the concurrency constructs

successfully address the main issues underlying concurrent programming. The further study of

the language reveals several deficiencies in its support for object-oriented software development

that are due to the interference of concurrency and object-oriented features. These are revealed

by the difficulties in using or taking full advantage of the object-oriented features for program-

ming concurrent objects. More specifically we will discuss the following issues concerning the

integration of concurrency and object-oriented programming that came out in our experience

with Hybrid:

• Encapsulation and intra-object concurrency. Hybrid adopts an active object model where do-

mains are the units of concurrent execution. This approach protects, by default, objects from

concurrent invocation of their operations. This extends the protection of the internal state of

Page 49: Language Design Rationale and Semantic Framework for

The Integration of the Concurrency and Object-Oriented Features34

objects provided by encapsulation to encompass concurrency. However, with this approach

objects cannot be internally concurrent. As we discuss below this choice affects the support

for data abstraction. It is essential for a COOPL to support data abstractions that use internal

concurrency for servicing requests.

• Combining synchronization with class inheritance. Although Hybrid supports multiple inher-

itance it is difficult to take advantage of inheritance when classes make use of delay queues.

• Constructing data abstractions with concurrent implementations. It should be possible, when

desirable, to hide from the clients of an object, implementation decisions such as scheduling

and concurrently processing of requests. In Hybrid this is not always possible because of the

semantics of delegated calls.

2.4.1 Encapsulation and Intra-Object Concurrency

The approach taken in Hybrid to consider domains as the units of parallel execution provides a

synchronization boundary that is coarser than the encapsulation boundary provided by objects.

A domain consists of at least one object and its subobjects which are encapsulated within it and

possibly other, explicitly created, objects whose existence is not confined by the enclosing ob-

ject. Domains provide, by default, mutual exclusion at the object level which protects objects

from concurrent invocations.

Mutual exclusion at the object level adequately extends encapsulation and data abstraction

supported by objects to encompass concurrency. The integrity of an object’s state is protected

from the hazards of concurrent invocation of its methods which share its state. Mutual exclusion

is provided by default so one does not have to impose it as a requirement on the object’s imple-

mentation.

The fact that domains and consequently objects are the unit of concurrency does not permit

intra-object concurrency. In order to implement an object that uses concurrency for increased

throughput intra-object concurrency has to be simulated by a collection of independent objects

capable of concurrent execution that cooperate to implement the intended functionality. One of

these objects provides the interface to clients of the collection hiding the fact that a collection of

concurrent objects rather than a single object is used for implementing its services.

The implementation of an object as a collection of concurrently executing objects may

however present some difficulties.

• It may be difficult to abstract from the fact that the object is implemented by a collection of

objects. This happens in Hybrid as we discuss in 2.4.3. when delegated calls are used for im-

Page 50: Language Design Rationale and Semantic Framework for

Chapter 2 35

plementing objects concurrently. Delegated calls cause the caller’s domain to become idle.

This may cause a message to be accepted by other objects in the domain which may not be in

a state appropriate for accepting the message. In order to prevent this effect, objects whose

implementations make delegated calls should be created as separate domains.

• Depending on the constructs provided for object interaction the decomposition of an object

into a collection of interacting objects may be complex and present substantial overhead due

to the number of messages exchanged between components. Here the decomposition is car-

ried out to take advantage of potential concurrency among objects rather than to represent sep-

arate entities. The encapsulation that is provided by objects may work against us because the

object’s state is partitioned to provide concurrent execution.

The issue of protecting an object’s state from concurrent execution is important but it is not a

reason for not supporting or overlooking intra-object concurrency. Objects can be protected

from external concurrency by synchronizing invocation without forcing them to be internally se-

quential. However, if a language takes the approach to support concurrent implementations by

a collection of interacting objects, special attention should be paid in the design of its concur-

rency constructs so that it is possible for a collection of cooperating objects to be equivalent, in

some sense, to a single object.

2.4.2 Combining Synchronization and Inheritance

The main problem for supporting inheritance in a COOPL is to combine the synchronization

constraints of the inherited methods with those of the new methods defined in a subclass and, at

the same time, support some encapsulation between classes and their subclasses. These difficul-

ties arise in several object-oriented languages [3][27][41][69]. Here, we present the problem as

it occurs in Hybrid. In chapters 3 and 4 we will examine more language designs and we are also

going to discuss some promising approaches[41][80].

The synchronization constraints on the execution of an object’s operations are expressed in

Hybrid by using delay queues. In order to synchronize the execution of an operation with the

object’s state the operation is associated with a delay queue. The delay queue should be open or

closed respectively for the object’s states in which the operation’s execution may or may not

take place. The operations that modify the object state should take care to open and close the

delay queues according to the resulting state. This way of synchronizing operation execution, by

opening and closing delay queues, presents two difficulties when combined with class inherit-

ance:

Page 51: Language Design Rationale and Semantic Framework for

The Integration of the Concurrency and Object-Oriented Features36

• It may be necessary to redefine the inherited methods: The new methods defined by a subclass

may need to synchronize their execution with the object’s state. To achieve this synchroniza-

tion new delay queues may need to be defined by the subclass and be associated with the new

methods. The trouble is that inherited methods may modify the objects state in a way that re-

quires some of the delay queues defined by the subclass to be opened or closed. This eventu-

ality makes it necessary to examine the modifications performed by inherited methods to the

object’s state and to redefine those that should open or close some delay queues. Moreover,

the examination of the inherited methods is not restricted to methods of the parent class but

extends to all ancestor classes whose methods may modify the object’s state.

• It is difficult to support encapsulation among subclasses and parent classes: Delay queues are

defined as instance variables of type delay. In order to open and close the delay queues asso-

ciated with the methods of the parent class, the methods of the subclass access the implemen-

tation of the parent class. This violates the encapsulation of object classes [75] causing unde-

sirable dependencies between the internal representation of classes and their superclasses.

2.4.3 Data Abstractions with Concurrent Implementations

One of the benefits of data abstraction provided by objects is that it separates the issues concern-

ing what “services” are provided at an object’s interface from the way that they are implemented.

This separation of concerns encourages the development of systems that are open in respect to

refinements and extensions brought to objects as long as they present upward compatible inter-

faces.

This separation of interface and implementation for COOPLs would mean that different

implementations of objects could define different policies for scheduling requests, processing

requests in parallel or using internal parallelism for increased throughput. For instance, a disk

head scheduler object could use a variety of scheduling policies [77] in its implementation. As

another example, consider a symbol table object. It could be implemented sequentially forcing

all requests to be executed one after the other, or it could service requests in parallel by imple-

menting a readers-writers [23] scheduling scheme.

The implementation of objects that service requests in parallel and the implementation of

general request scheduling policies are achieved in Hybrid as shown in 2.2.2 and 2.2.3 by using

the delegated call mechanism. In the design of the concurrency constructs, considering concur-

rency and data abstraction to be orthogonal, not much attention was paid to support of delegated

calls for data abstraction. It turned out by further experience with the language that special care

has to be taken for using objects whose implementations make use of delegated calls and for re-

Page 52: Language Design Rationale and Semantic Framework for

Chapter 2 37

placing an object implementation by one that makes use of this mechanism. This makes it nec-

essary to be aware of the use of gelegated calls and constrains the implementation of objects.

Thus, it diminishes the benefits of data abstraction.

Consider an objectA which calls a method of another objectB which is in the same domain.

If B issues a delegated call its domain becomes idle and objects in the domain may accept further

call or return messages.Thus, the delegated call inB may trigger the execution of a method of

any object of the domain because of the acceptance of a pending call message. In particular, it

may trigger the execution of another method ofA. This causes an interleaved execution ofA’s

methods as the execution of the method that invokedB in the first place is not yet completed.

This interleaved execution occurs in points that are not controlled byA but may cause the exe-

cution ofA’s method to fail. The class invariant, which is a necessary precondition for the correct

execution ofA’s methods[37][54], may not hold whenA callsB or any other object.

This problem may be circumvented by an appropriate implementation ofA that takes into

account the fact that delegated calls take place withinB. It is possible to implementA in such a

way that the class invariant is satisfied before callingB’s methods or to prevent the activation of

otherA’s methods by using delay queues or by havingA andB be in separate domains. These

solutions, which are inconvenient, rely on the fact that it is known thatB’s implementation uses

delegated calls. It would be unrealistic to require that the class invariant hold before calling any

other object or to implement every object called by A as a separate domain to foresee the even-

tuality of delegated calls.

The ways, mentioned above, to cicumvent the problem with delegated calls are contrary to

data abstraction, since it is necessary to know how an object is implemented in order to construct

correct programs. Furthermore, it is not possible to safely replace the implementation of an ob-

ject that doesn’t use delegated calls by one that does without re-examining all the programs that

were based on the old implementation.

2.5 Summary

Hybrid served as a concrete example showing that the successful integration of concurrency and

object-oriented programming requires a lot more than a syntactic integration of the concurrency

constructs with object-oriented features. Moreover, the examination of Hybrid’s features al-

lowed us to gain more insight into the general issues underlying the design of concurrent object-

oriented languages and the integration of concurrency and object-oriented programming.

Page 53: Language Design Rationale and Semantic Framework for

Summary38

• The active view of objects is appropriate for supporting encapsulation and protecting the

internal state of objects from concurrent invocations and makes it possible to reuse ob-

jects in concurrent applications. The approach taken for implementing Hybrid shows that

this view of objects can be supported without having to implement all objects as process-

es which would be unrealistic in systems where context switching and inter-process

communications are a lot more expensive than procedure calls.

• Synchronization of method execution interferes with class inheritance and encapsula-

tion. As it is the case with delay queues, method synchronization should not be specified

in terms of the instance variables of objects. Such an approach makes it necessary to vi-

olate encapsulation in order to synchronize the execution of methods of a class with those

of its superclass and it may also be necessary to redefine the inherited methods.

• Scheduling of requests by objects and concurrent implementations of objects should be

supported in a way that is consistent with data abstraction. Although the concurrency

constructs of Hybrid are satisfactory for request scheduling and for concurrent imple-

mentations they do not adequately support data abstraction. In general for request sched-

uling and for concurrent implementations it is needed to use several objects and delegat-

ed calls. However, objects that are implemented by using delegated calls are not, in gen-

eral, substitutable with those that do not, despite the fact that they may present the same

interface and provide the same services to their clients.

It is important to note that the deficiencies of Hybrid’s concurrency constructs for support-

ing an object-oriented programming style that promotes reuse were uncovered by constructing

appropriate examples, or rather counter-examples. These illustrated situations where the design

of the language features made it difficult to take advantage of object-oriented techniques such

as data abstraction and inheritance. In order to be more confident about the support for OO pro-

gramming provided by the other design alternatives that we examine in chapter 3, we would like

to develop more systematic ways for evaluating and comparing language features with respect

to their support for OO programming. Along this direction in chapter 4 we develop a list of in-

formal requirements that we use for comparing the design alternatives discussed in chapter 3.

Also, the semantic framework for describing the semantics of COOPL features, developed in

chapter 5, is, as we discuss in chapter 6, a step towards a more rigorous approach for examining

the interaction and evaluating the integration of object-oriented and concurrency features.

Page 54: Language Design Rationale and Semantic Framework for

CHAPTER 3

A Design Space for ConcurrentOOPLs

A large number of concurrent object-oriented languages have been designed and implement-

ed[69]. These languages vary considerably in the design of their concurrency features and in the

way that they are combined with the object-oriented features. The various design choices taken

in these languages are not equally successful in integrating concurrency and object-oriented fea-

tures, and consequently, for taking advantage of object-oriented techniques and their software

reuse potential in the construction of concurrent software.

A language may support features characterizing it as object-oriented [87] as well as con-

currency constructs that successfully address the main issues underlying concurrent program-

ming [9]. However, the concurrency features may interfere with the object-oriented features pre-

venting the latter to fullfil their purpose and effectively support object-oriented programming

techniques. The presentation of Hybrid in chapter 2 showed how this interference may occur in

several aspects of the design of a language.

In order to understand what are the essentially different design choices with respect to their

support for object-oriented programming we construct a language design space that expresses

these choices in terms of the relationship between objects and concurrency. This design space is

used in next chapter for evaluating the support for object-oriented programming achieved by de-

sign alternatives.

We start by presenting three aspects of COOPLs that we consider for constructing the de-

sign space. Then we discuss the design choices which respect to each of these aspects. In section

3.5 we examine more closely some existing languages showing how the design of their features

Page 55: Language Design Rationale and Semantic Framework for

40 A Design Space for Concurrent OOPLs

situate them in the design space. We finally summarize by presenting a number of tables dis-

playing how the surveyed languages’ features are classified in terms of the design space. We also

discuss some cases where the reasons for classifying a language’s feature in a certain way may

not be obvious.

3.1 A Design Space for Concurrent OOPLs

We seek to evaluate language design choices with respect to the integration of their concurrency

and object-oriented features and the degree to which software reuse is supported. In particular,

we wish to understand how choices of concurrency constructs interact with object-oriented tech-

niques and affect the reusability of objects. As such, our classification scheme concentrates on

the relationship between objects and concurrency. We shall consider the following aspects:

• Object Models: how is object consistency maintained in the presence of concurrency?

The way objects are considered with respect to concurrent execution may or may not pro-

vide them with a default protection with respect to concurrent invocations.

• Internal Concurrency: can objects manage multiple internal threads? This issue con-

cerns the expressive power that is provided to objects for handling requests. The execu-

tion internal threads is also related to the protection of the internal state objects. This is,

however, a separate issue that is addressed by the choice of the object model discussed

above.

• Constructs for Object Interaction: how much freedom and control do objects have in

sending and receiving requests and replies? The choice of concurrency constructs for

sending and receiving messages determines the expressive power that is provided for im-

plementing concurrent objects. Moreover, the design of constructs for conditional accep-

tance of messages interacts with the use of class inheritance.

In the presentation of the design space, it will become apparent that these aspects are not entirely

independent: certain combinations of choices are contradictory and others are redundant or lack

expressive power.

3.2 Concurrent Object Models

We shall first consider whether or not objects are provided with a default means of protecting

internal consistency in the presence of concurrent requests. There are three main approaches:

Page 56: Language Design Rationale and Semantic Framework for

Chapter 3 41

• The Orthogonal Approach:Concurrent execution is independent of objects. Synchronization

constructs such as semaphores in Smalltalk-80 [34], “lock blocks” as in Trellis/Owl [60] or

monitors as in Emerald[14] must be judiciously used for synchronizing concurrent invoca-

tions of object methods. In the absence of explicit synchronization, objects are subject to the

activation of concurrent requests and their consistency may be violated.

• The Homogeneous Approach:All objects are considered to be “active” entities that have

control over concurrent invocations. The receipt of request messages is delayed until the ob-

ject is ready to service the request. There is a variety of constructs that can be used by an ob-

ject to indicate what method invocation it is willing to accept next. In POOL-T [5]this is spec-

ified by executing an explicit accept statement. In Rosette [80]anenabled set is used for spec-

ifying which set of messages the object is willing to accept next.

• The Heterogenous Approach: Both active and passive objects are provided. Passive objects

do not synchronize concurrent requests. Examples of such languages are Eiffel //[54][21] and

ACT++ [41]. Both languages ensure that passive objects cannot be invoked concurrently by

requiring that they be used only locally within single-threaded active objects.

Although most COOPLs fall clearly within one of these three categories, there are a number of

limit cases. For example, Argus[51] appears to support a heterogeneous model since it provides

bothguardians (active objects) and CLU [48]clusters (passive objects), but the synchronization

of multiple threads within guardians corresponds to the orthogonal model.

3.3 Internal Concurrency

Wegner [87] classifies concurrent object-based languages according to whether objects are in-

ternally sequential, quasi-concurrent or concurrent:

• Sequential Objectspossess a single active thread of control. Objects in ABCL/1[92] and

POOL-T and Ada tasks [8] are examples of sequential objects.

• Quasi-Concurrent Objects have multiple threads but only one thread may be active at a time.

Control must be explicitly released to allow interleaving of threads. Hybrid domains[62] and

monitors[38] are examples of such objects.

• Concurrent Objects do not restrict the number of internal threads. New threads are created

freely when accepting requests. Adapackages and POOL-Tunits resemble concurrent objects

(though they are not first class objects). Languages like Smalltalk-80 that adopt the orthogonal

Page 57: Language Design Rationale and Semantic Framework for

42 Internal Concurrency

object model also support concurrent objects in the sense that a new local thread is effectively

created whenever a method is activated in response to a message.

According to the above classification, the threads of concurrent objects are created freely

when a message arrives to an object. However, there are languages where objects may have in-

ternally y concurrent threads that are not freely created by message reception. In order to include

these languages in the classification and to capture more information about the way that threads

are created, we generalize the concurrent object class to include any language in which objects

have concurrent threads, irrespective of the way they are created, and consider separately the is-

sue of thread creation.

We define three, non-exclusive, ways for the creation of threads within objects as follows:

• By message reception: Thread creation is triggered by reception of a message. Depending on

whether objects may control the creation of threads we have the following sub-categories:

• Controlled by the object:The object may delay the creation of threads. For example, in

the language SINA [81] a new concurrent thread may be created for the execution of a

method belonging to a select subset of the object’s methods only if the currently active

thread executes thedetach primitive.

• Unconstrained creation:Threads are created automatically at message reception. This is

the default for languages with an orthogonal object model.

• Explicit creation: Thread creation is not triggered by message reception but by the execution

of some construct by the object. For instance, in SR [10] there is a construct similar to a “cobe-

gin“[9] to initiate the execution of concurrent threads

Thenext andbecome primitives in Rosette and ACT++ can be viewed as a controlled cre-

ation of threads, with the additional restriction that concurrent threads may not share the object’s

state since they execute on different “versions” of the object.

Internal Concurrency

SEQUENTIAL

Single thread of control

ABCL/1, POOL-T

QUASI-CONCURRENT

There are several logical threads butonly one at a time. Thread interleavingoccurs at programmer defined places

Hybrid, monitors

CONCURRENT

There may be several threads ofcontrol active within an object.

Page 58: Language Design Rationale and Semantic Framework for

Chapter 3 43

In Guide [43], an object may be associated with a set of activation conditions that specify

which methods may be executed in parallel by internally concurrent threads. In the default case,

as with any language following an orthogonal approach for concurrency, objects may be viewed

as concurrent with unconstrained creation of threads triggered by external messages.

The creation of threads by reception of external messages or by execution of a special con-

struct are neither mutually exclusive design choices, as illustrated by SR which supports both,

nor redundant as we will find out in the next chapter.

3.4 Constructs for Object Interaction

We classify these constructs with respect to the degree of control that can be exercised by objects

in the client and server roles. We specifically considerreply scheduling, which concerns the de-

gree of flexibility the client has in accepting a reply, andrequest scheduling, which concerns the

control the server can exercise in accepting a request.

3.4.1 The Client’s View - Issuing Requests

From the client’s point of view, there are three important issues concerning the constructs sup-

ported for issuing requests:

• Interleaving activities: Can the current thread continue after issuing the request?

• Reply address: How and where is the reply to be sent? Flexible control over the reply desti-

nation can reduce the amount of message passing required.

• Getting the reply: What mechanisms are supported for matching replies to requests? How

does the client synchronize itself with the computation and delivery of the reply?

We initially distinguish betweenone-way message passing communication primitives and con-

structs supporting arequest/reply protocol. The latter provide support for object interactions

Thread Creation

BY MESSAGE RECEPTION EXPLICIT CREATION

SR co, Smalltalk-80 fork

UNCONSTRAINTEDCREATION OF THREADS

⇒ORTHOGONAL OBJECT MODEL

Smalltalk-80, Ada packages

CREATION OF THREADS ISCONTROLLED BY THE OBJECT

SINA, Act++

Page 59: Language Design Rationale and Semantic Framework for

44 Constructs for Object Interaction

where requests will be eventually matched by replies. These primitives vary in the flexibility in

sending requests and receiving replies. Strict rpc approaches enforce that requests will be

matched by a reply and delay the calling thread until the reply is available. Further flexibility is

provided by “proxy” objects which disassociate the sending or receiving of messages from the

current thread of control. Examples of build-in proxy objects arefuture variables[92] andCBox-

es[90].

One-way Message Passing

Whether communication is synchronous, as in CSP[39] or PROCOL [84], or asynchronous, as

in actor languages, clients are free to interleave activities while there are pending requests. Sim-

ilarly, replies can be directed to arbitrary addresses since the delivery of replies must be explic-

itly programmed.

The main difficulty with one-way message passing is getting the replies. The client and the

server must cooperate to match replies to requests. As we shall see in chapter 4, the additional

flexibility and control provided by one-way message passing over request/reply based approach-

es can only be properly exploited if objects (i.e., servers) are implemented in such a way that the

reply destination can always be explicitly specified in a request.

Remote Procedure Call

With RPC the calling thread of the client is blocked until the server accepts the request, performs

the requested service and returns a reply. Most object-oriented languages support this form of

interaction, though “message passing” is generally compiled into procedure calls.

Supporting RPC as the only means for object interaction may be a disadvantage when ob-

jects are sequential as we will see in the next chapter. Although it is trivial to obtain a reply, it

is not possible to interleave activities or to specify reply addresses.

Client/Server Interaction

ONE-WAY MESSAGE PASSING

Higher-level protocols must be ex-plicitly programmed

PROCOL, CSP

REQUEST/REPLY

Balanced requests andreplies are supported.

PROXIES

Sending requests and receiving replies maybe delegated, as with CBoxes andfutures

ABCL/1, ConcurrentSmalltalk, Eiffel //

RPC

Sending a request blocks thecurrent thread until a reply isreceived.

Page 60: Language Design Rationale and Semantic Framework for

Chapter 3 45

Proxies

An alternative means which provides the client with more flexibility in sending and receiving

replies is to introduceproxies. The main idea is to delegate the responsibility of delivering the

request and obtaining the reply to a proxy. (The proxy need not be a first-class object, as is the

case withfuture variables [92].) The actual client is therefore free to switch its attention to an-

other activity in the mean time. The proxy itself may also perform additional computation or call

multiple servers.

If necessary, the reply is obtained by the original client by an ordinary (blocking) request.

This approach, variants of which are supported by several languages [21][92][90], maintains the

benefits of an RPC interface and the flexibility of one-way message passing. In contrast to one-

way message passing, however, there is no difficulty in matching replies to requests.

A closely related approach is to combine RPC with one-way message passing. In ABCL/1,

for example, an object that externally has an RPC interface may internally use lower level mes-

sage passing primitives to reply by sending an asynchronous message to the client or to its proxy.

The use of such facilities is further discussed in chapter 4.

3.4.2 The Server’s View - Constructs for Accepting Requests

A main concern from the point of view of an object acting as a server is whether requests can be

conditionally accepted1. When a request arrives the server may be busy servicing a previous re-

quest, waiting itself for another request to be fulfilled, or idle, but in a state that requires certain

requests to be delayed. We distinguish initially between conditional and unconditional accep-

tance of requests. Conditional acceptance can be further discriminated according to whether re-

quests are scheduled by an explicit acceptance, by activation conditions or by means of reflec-

tive computation:

Unconditional acceptance

Unconditional acceptance of requests is illustrated by monitors[38] and by Smalltalk-80 [34]

objects. The mutual exclusion that is provided by monitors could be considered as an implicit

condition for the acceptance of requests. However, the mutual exclusion property is captured by

viewing monitors as quasi-concurrent objects so we consider request acceptance to be uncondi-

1. A secondary issue is whether further activity related to a request may continue after the reply has been

sent as in the Send/Receive/Reply model [32], but this can also be seen as concern of internal concurrency

where follow-up activity is viewed as belonging to a new thread.

Page 61: Language Design Rationale and Semantic Framework for

46 Constructs for Object Interaction

tional. Note that message acceptance for languages with an orthogonal object model is by default

unconditional.

Explicit acceptance

With explicit acceptance, requests are scheduled by means of an explicit “accept” statement ex-

ecuted in the body of the server. Accept statements vary in their power to specify which messag-

es to accept next. Acceptance may be based on message contents (i.e., operation name and argu-

ments) as well as the object’s state. Languages that use this approach are Ada, ABCL/1, Con-

current C, Eiffel //, POOL-T and SR. With this approach objects are typically single-threaded,

though SR is an exception to this rule.

Activation conditions

With activation conditions, requests are accepted on the basis of a predicate over the object’s

state and, possibly, the message contents. The activation condition may be partly implicit, such

as the precondition that there be no other threads currently active within the object. An important

issue is whether the conditions are expressed directly on a particular representation of the ob-

ject’s state or if they are expressed in more abstract terms. In Guide, for example, each method

Request Scheduling

UNCONDITIONAL

No Synchronization withthe state of the target

ADA packets, Smalltalk-80, Emerald, Trellis/Owl.

EXPLICIT ACCEPTANCE

The execution of the opera-tion is synchronized with an“accept” statement explicitlyexecuted by the target.

ADA tasks, ABCL/1, SRPOOL-T, Eiffel//.

ACTIVATION CONDITIONS

Explicit or implicit conditions onthe target’s state determine whenthe execution of an operation maytake place.

The arrival of a message at the targettriggers a reflective computation in theassociated meta-object. This determineswhether the requested operation shouldbe executed.

ABCL/R, ACTALK

REFLECTIVE COMPUTATION

ABSTRACT –REPRESENTATIONSPECIFIC

REPRESENTATIONINDEPENDENT

Conditions are expressed in terms of ab-stract properties of the object and do notrefer to the particular implementation

ACT++, ROSETTE, PROCOL,PATH EXPRESSIONS

Condition are expressed directlyon the hidden object state.

GUIDE, Hybrid, SINA

ACCEPTANCE CONDITIONALACCEPTANCE

Page 62: Language Design Rationale and Semantic Framework for

Chapter 3 47

is associated with a condition that references the object’s instance variables, whereas in ACT++

the condition for accepting a message is that the object be in an appropriateabstract state which

abstracts from the state of a particular implementation. Another approach is to specify the legal

sequences of message acceptance by means of a regular expression, as in path expressions[19]

and PROCOL [84].

Reflective computation

With reflective computation the arrival of a request triggers a method of the server’smeta-ob-

ject. The meta-object directly then manipulates object-level messages and mailboxes as objects.

This approach is followed by the language ABCL/R [86] and it is also illustrated in Actalk[18]

where some reflective facilities of the Smalltalk-80 system are used to intercept messages sent

to an object and synchronize their execution in a way that simulates message execution in actor-

based languages.

3.5 Classification of Existing Languages

3.5.1 The Orthogonal Approach

Smalltalk-80

Smalltalk-80 [34] supports concurrent programming by processes that communicate through

shared objects. The creation of processes is accomplished by sending a fork message to a block

context and semaphores are provided for their synchronization and mutual exclusion.

The object model is orthogonal to concurrent execution. The protection of objects from

concurrent execution is ensured by judicious use of semaphores. This can be done in two ways.

Either the calling process uses semaphores before invoking operations on shared objects or the

execution of an object’s operations is synchronized by using semaphores in its implementation.

As we see later both these ways interfere with support for object reuse and with class inheritance.

The objects may be classified as internally concurrent since several threads may execute

concurrently within an object. The execution of threads in a Smalltalk-80 system is essentially

quasi-concurrent as the active thread has to explicitly give up the “cpu.” However, objects do

not have full, local control over the quasi-concurrent thread execution.The suspension of the cur-

rent thread and the activation of another may take place in some other object. For this reason we

view objects as being internally concurrent.

Page 63: Language Design Rationale and Semantic Framework for

48 Classification of Existing Languages

The creation of threads may be initiated either by messages sent to the objects or by the ob-

ject itself by sending a fork message to a local block. The creation of threads by reception of

messages is not controlled by the object.

Object interaction may be characterized as following a remote procedure call model where

a new thread is created automatically for handling calls in the called object. There are no con-

structs for expressing conditional acceptance of messages. This has to be programmed by sus-

pending, through the use of a semaphore, the threads created for executing methods that cannot

be processed in the current object’s state.

It is interesting to note that some reflective facilities of the Smalltalk system may be used

to easily accommodate different object models and object interaction constructs[17][73]. The

approaches are based on a facility that is provided in Smalltalk for error handling. This allows

the reception of a message to intercepted and triggers the execution of a method to which the

message is provided as an argument. This method may decide to execute or delay the execution

of the requested method according to the simulated object model. Furthermore, as in Smalltalk

blocks are first class objects, various approaches for conditional acceptance may be nicely pack-

aged as constructs.

Emerald

Emerald [14] is an object-oriented language for programming distributed applications. An ob-

ject may be associated with a process that starts executing after the object has been created and

initialized.

The operations of objects may be invoked concurrently by their own process, if they have

one, and by those of other objects. Synchronization of processes and mutual exclusion is accom-

plished by using monitors [38]. A number of monitors may be used in the implementation of ob-

jects and their operations may be implemented as monitor procedures. This approach is more

flexible than viewing the whole object as a single monitor since it allows operations that are not

implemented as monitor procedures or that are in different monitors to execute in parallel.

The orthogonal approach is followed for the object model. Objects are not protected from

concurrent execution unless monitors are used in their implementation.

Objects are internally concurrent. The creation of threads within objects, apart from the

thread that may declared within the object, is triggered by external messages and cannot be ini-

tiated by the object itself. If an object needs to create a new internal thread it has to create a new

Page 64: Language Design Rationale and Semantic Framework for

Chapter 3 49

object that will invoke one of its operations. Remote procedure call is used for object communi-

cation and no constructs are provided for conditional acceptance of requests.

Trellis/Owl

Trellis/Owl [60] supports concurrent execution by explicit creation of concurrent threads called

activities for the execution of an operation. Activities may be created for the execution of any

operation and they communicate by invoking the operations of shared objects. The language de-

fined typeslock andwait queue are provided to support synchronization and mutual exclusion.

Objects of these types may be defined as instance variables of an object. Mutual exclusion is

achieved by associating code blocks with locks. Combinations oflock blocks, blocks associated

with locks, and wait queues may be used for implementing objects similar to monitors, yet they

allow more flexibility than monitors, since some operations may be allowed to execute concur-

rently.

There is also support for direct synchronization of activities. An activity may wait until

some other activity terminates. A typeActivity_Set is also providedfor allowing an activity to

wait until one or all of the activities in the set terminates.

Figure 3.1 illustrates the use of locks and wait queues in the implementation of a character

buffer of unbounded size that may be shared by concurrently executing activities.

The orthogonal approach is taken for the object model as no default protection of objects is

provided. Objects are internally concurrent. Concurrent threads may be created either by the re-

ception of messages or by the object by creating a new activity for the execution of some oper-

ation. Object interaction takes the form of remote procedure calls and acceptance of requests is

unconditional.

Guide

In Guide [43] threads, called activities, communicate by calling the operations of shared passive

objects. The synchronization mechanism consists of associating anactivation condition with the

object’s operations which must be true before the execution of an operation may take place. Ac-

tivation conditions are boolean expressions that may refer to arguments of the invoked opera-

tion, instance variables, a number ofsynchronization counters and operation names. Synchroni-

zation counters are associated with an operation and record automatically the number of started,

completed, pending and ongoing executions of an operation. For instancestarted(op) is the num-

Page 65: Language Design Rationale and Semantic Framework for

50 Classification of Existing Languages

ber of initiated execution of operationop, completed(op) is the number of terminated executions

of op andcurrent(op) is equivalent tostarted(op) - completed(op). Some keywords are used as

syntactic sugar for commonly used activation conditions. For instance the keyword EXCLU-

SIVE may be used in the activation condition of an operation for expressing mutual exclusion.

The same thing can also be done by having an activation condition stating that the sum ofcur-

rent(op) over all operationsop of the object must be equal to zero. The keyword NOT followed

by the name of an operation specifies that there cannot be any ongoing executions of the speci-

fied operation.

Figure 3.2 illustrates the use of activation conditions in the implementation of a bounded

buffer in Guide. TheCONTROL clause specifies the activation conditions for the operationsGet

andPut. The term “NOT Get AND NOT Put” specifies mutual exclusion of both operations. Re-

placing this term by the keywordEXCLUSIVE would have the same effect. The term “nbr < size”

Figure 3.1 Lock blocks in Trellis/Owl

type_module Shared_char_Buffer

component me.mutex : Lock;component me.nonempty : Wait_Queue;component me.buffer : Char_Queue;

operation create (Mytype) returns (Mytype)is allocatebegin

me.mutex := create(Lock);me.nonemoty := create(Wait_Queue);me.buffer := create(Char_queue);

end;

operation insert(me, x: Char)is begin

lock me.mutex doinsert(me.buffer,x);wakeup(me.nonempty);

end lock;end;

operation remove (me) returns (Char)is begin

lock me.mutex doif( empty(me.buffer)) then

wait(me.nonempty)end if;return remove (me.buffer);

end lock;end;

end type_module;

Page 66: Language Design Rationale and Semantic Framework for

Chapter 3 51

in the activation condition forPut prevents the execution ofPut when the buffer is full. Similarly

nbr > 0 prevents the execution ofGet when the buffer is empty. The code of the operationsPut

andGet does not include any synchronization primitives.

Guide takes also an orthogonal approach for its object model as, by default, objects are not

protected from concurrent execution. Object are internally concurrent.Thread creation is trig-

gered either by reception of messages or by the execution of acobegin statement used for creat-

ing new activities. Object interaction takes the form of remote procedure calls. Conditional ac-

ceptance of requests is expressed by activation conditions that depend on the object’s internal

state.

ConcurrentSmalltalk

ConcurrentSmalltalk [90]is an extension of Smalltalk-80. The aims in the design of this lan-

guage were to provide a better integration of concurrent programming with objects than is the

case with processes and semaphores in Smalltalk-80.

Figure 3.2 Activation conditions in Guide

TYPE boundedBuffer ISMETHOD Put(IN i: Item);METHOD Get(OUT i: Item);

END boundedBuffer

CLASS FixedSizeBuffer ISIMPLEMENTS boundedBuffer;

CONST size = some constantbuffer: ARRAY[0..size-1] of Item;nbr , first, last: Integer = 0, 0, 0;

METHOD Put( IN i: ITEM );BEGIN

...code for put...END Put;

METHOD Get( OUT i: Item );BEGIN

...code for get...END Get;

CONTROLPut: NOT Get AND NOT Put AND nbr < size;Get: NOT Get AND NOT Put AND nbr > 0

Page 67: Language Design Rationale and Semantic Framework for

52 Classification of Existing Languages

The concurrent features introduced are: asynchronous method invocation, allowing meth-

ods execution to proceed after returning a result, Cbox objects for synchronization, and anatom-

ic object class.

Asynchronous method invocation is specified by terminating the method invocation ex-

pression by the symbol “&.” An asynchronous method invocation expression returns a newly

created CBox object. The caller may bind the CBox object to a variable and use it later for re-

ceiving the result of an asynchronous method invocation. The result associated with the CBox

object is obtained by invoking areceive method defined on CBox objects. If the result is not

available whenreceive is invoked the invoker is suspended. CBox objects are used for synchro-

nizing the caller of an asynchronous method invocation with the called object and act as a private

communication channel for getting the reply. Without CBox objects, it would be difficult for the

sender of an asynchronous message to identify the replies.

The atomic object class is used to define subclasses whose instances have the property that

execution of their methods is mutually exclusive. This is needed for preventing problems that

may be caused by concurrent execution of an object’s methods.

A problem with the concurrency features in the first design of ConcurrentSmalltalk[90]

was that it provided limited support for condition synchronization. There was no means for se-

lective acceptance of messages and no direct way to suspend the execution of method unless on

resorted to Smalltalk-80 semaphores. In a later version of the language [91] this was overcome

by introducing the concept ofsecretary objects. These are special objects that may be attached

to ordinary objects and are used for synchronizing the execution of threads within the object and

for managing the acceptance of messages.

Objects, apart from atomic ones, are ordinary Smalltalk objects that are internally concur-

rent. Communication takes place by remote procedure calls as in Smalltalk-80 or by a non block-

ing variant that may be combined with CBox objects for receiving the replies.

The object model could be characterized as heterogenous since two kinds of objects, atomic

and ordinary Smalltalk objects, are supported. However, unlike other languages that we consider

to have an heterogenous model the protection of objects is not enforced by the system. It is the

programmer that is responsible to define objects that are subject to concurrent access as atomic

ones. This not very different from the use of synchronization constructs in orthogonal languages

to protect shared objects from concurrent execution. This is why we consider it as a language

with an orthogonal object model.

Page 68: Language Design Rationale and Semantic Framework for

Chapter 3 53

SR

SR (Synchronizing Resources) [10] is a programming language for distributed applications. Al-

though it is not advertised as an OOPL it supports several object-oriented features. Programs are

structured in terms of resources. A resource encapsulates variables and processes. Resource

specifications declare operations that are used for interacting with a resource. A resource may

be implemented as an abstract data type, by specifying a procedure for each operation, or by one

or more processes. Figure 3.3 shows a resource that implements a queue of integers as an ab-

stract data type.

Resources implemented as processes may selectively service operation invocations by us-

ing in statements. This is similar to Ada’s select/accept [8] but more powerful since it allows

guards to depend on the arguments of the invocation.

Resources are typed and may be created dynamically. Inheritance is supported by anextend

construct which is used to refine a resource specification and provide different implementations

of the resource’s operations. It is possible to defineabstract resources consisting only of a spec-

ification.

Figure 3.4 shows the implementation of a resource that extends the queue given earlier and

implements it by a single process so that it can be used as a bounded buffer. This ensures mutual

exclusion as only this process may access the resource’s state.

Figure 3.3 A queue in SR as a passive data type

resource Queueop insert(item: int)op remove() returns item: int

body Queue(size: int)var store[0..size-1] : intvar front := 0, rear := 0, count :=0

proc insert(item)if count < size -> store[rear]:=item; rear:=(rear+1)%size;

count++;[] else -> #take action appropriate for overflowfi

end

proc remove() returns item

... implementation of remove...end

end Queue

Page 69: Language Design Rationale and Semantic Framework for

54 Classification of Existing Languages

Capability variables to abstract resources may be used to refer to any concrete resource that

extends an abstract resource by providing it with abody. It should be noted that this mechanism

may not be used for inheriting methods as in languages like Smalltalk-80, but it is solely used at

the operation specification level to express a subtype relationship.

Resources are concurrent objects. Threads are created either by reception of external mes-

sages, in the case that the resource is implemented as an abstract data type, or by the execution

of theco construct which is similar to a “cobegin.” Protection of a resource’s state from concur-

rent execution is achieved by implementing a resource as a single process as shown above for

the bounded buffer.

The object model of resources may be characterized as orthogonal. No distinction is made

between resources that are implemented as abstract data types whose operations should not be

called concurrently, and resources implemented as processes that control the activation of their

operations which can may therefore be invoked concurrently.

Resource interaction takes the form of remote procedure calls. A variant that does not

block the caller is also provided. However, there is no support for getting the result of a non

blocking call and thus results are discarded. Explicit acceptance of requests by “in” statements,

described above, is the main means for achieving conditional acceptance of requests.

Figure 3.4 A queue in SR implemented as a process

resource BoundedBufferextend Queue

body BoundedBuffer(size: int)var store[0..size-1] : intvar front := 0, rear := 0, count :=0

process bb

in insert(item) and count < size ->

store[rear]:=item; rear:=(rear+1)%size; count++;

[] remove() returns item and count>0 ->

item := store[front]; front:= (front+1)%size; count--; niend

end BoundedBuffer

Page 70: Language Design Rationale and Semantic Framework for

Chapter 3 55

3.5.2 The Heterogenous Approach

PAL

The programming language PAL, used in the AVANCE [13] system, supports two kinds of ob-

jects:packets anddatatype values. Packets are associated with persistence, resiliency, synchro-

nized access and independent existence. Datatype values are instances of abstract data types.

Datatype values may only be used within a packet so that they are protected from concurrent ac-

cess by the serialized execution of the operations of the enclosing packet. A new thread may be

created for the execution of any PAL expression. Execution of an expression by a new thread

creates an instance of a process datatype that may be used in way similar to ConcurrentSmall-

talk’s Cbox objects for obtaining the computed result. Process communication takes place by in-

voking the operations of shared packets.

The distinction between packets and datatypes in PAL was made mainly because of the im-

plementation overhead associated with the execution of packets. The implementation of data-

type values has less overhead since execution of their operations does not have to be synchro-

nized. By restricting the use of datatype values within packets, datatype values are protected

from concurrent access.

The disadvantage of this approach is that datatypes and packettypes form two separate type

hierarchies that could contain objects with similar functionality: code that was written to operate

on datatypes may not be used for packettypes and vice versa. The decision of implementing an

object as a packettype or a datatype is left to the programmer, and it may depend on the intended

use of an object in a particular application.

With respect to our classification scheme, PAL supports an heterogenous object model. In-

ternal concurrency is supported by creating processes. However, these processes may not com-

municating by accessing concurrently the packets’ internal state but may communicate by in-

voking the operations of other packets. Communication is based on remote procedure calls. It is

also possible to generate non-blocking calls by executing the invocation expression by a new

thread. No mechanism is provided for conditional acceptance of requests.

Eiffel //

This is a concurrent extension [21]to the programming language Eiffel [54] that also takes the

approach of separating the object world into two kinds of objects:processes anddata objects.

Process objects are single threaded and when created execute the code of theirlive routine. A

Page 71: Language Design Rationale and Semantic Framework for

56 Classification of Existing Languages

process object accepts operation invocations explicitly by aServe statement within its live rou-

tine. TheServe statement is parameterized by a name of an operation.If there are pending re-

quests for this operation the oldest is accepted and it is executed. If there are no pending requests

for the specified operation theServe statement has no effect and the execution of the live routine

proceeds at the next statement.

The operations of process objects are always invoked asynchronously. An approach some-

what similar to ConcurrentSmalltalk’sCBoxes and ABCL/1’sfuture type messages is taken for

cases where operations return a result. When an operation of a process object is invoked an ob-

ject representing the result is returned immediately. The caller is suspended when it attempts to

use a result that is not yet available.

Data objects do not have a live routine and their operations are invoked as ordinary proce-

dure calls. They may only be used within a process object so that their operations are never in-

voked concurrently.

As both theServe primitive and operation invocations are non blocking, it is rather difficult

to synchronize process objects. The only ways are to use busy-waiting or to use the result re-

turned by operations. For instance, if a process object wants to accept a message before proceed-

ing with the execution of its live routine, the serve primitive specifying the operation has to be

included in a loop. This weak approach to synchronization may lead to complex solutions to syn-

chronization problems, where unneeded return values are used merely for synchronization, and

complicate the protocols for object interaction.

ACT++

ACT++ [41] is a object oriented language that extends C++ [76] with concurrency features de-

rived from the actor model [1]. It supports two kinds of objects: actors and passive objects. Ac-

tors are active objects that serialize concurrent invocation of their operations. Passive objects are

ordinary C++ objects. They are constrained to be used only within actors so that their operations

may not be invoked concurrently. Any C++ object may be an actor if its class is defined as a

subclass of a predefined actor class.

The main communication mechanism is remote procedure call. Concurrent execution is

supported by thereply andbecome primitives. Thereply primitive is used within an operation to

return a reply to the caller. Statements following the reply statement in an operation are executed

in parallel with the caller. Thebecome primitive is inspired from the replacement behavior in the

actor model. An actor object may use this primitive to specify a behavior name that is used to

Page 72: Language Design Rationale and Semantic Framework for

Chapter 3 57

indicate what message it is willing to accept next. Once the replacement behavior has been spec-

ified, through thebecome primitive, processing of messages may start according to the new be-

havior and in parallel with the statements following thebecome primitive in the old behavior.

The old and new behaviors do not share the actor’s internal state so no interference can occur

because of the parallel execution of behaviors.

Selective acceptance of requests is supported by the definition of behaviors, defined with

an actor class, in terms of the operations that they may process. Figure 3.5 sketches the definition

of an actor class that implements a bounded buffer of integers. The behavior part defines three

behavior names for bounded buffers. Theempty_buffer behavior accepts and processes the oper-

ationput. The behavior full_buffer accepts onlyget operations and the behaviorpartial accepts both

get andput operation invocations.

class bounded_buffer: Actor{

in_array buff[MAX];in in, out;behavior:

empty_buffer = { put()}full_buffer = { get() }partial_buffer = { get(), put() }

public:buffer(){

initialisation of the buffer ...become empty_buffer;

}insert an itemvoid put(in item){

if the buffer is now full

become full_buffer;else

become partial_buffer;}in get(){

return the next item ...reply buff[out++];if the buffer is now empty

become empty_buffer;else

become partial_buffer;}

}

Figure 3.5 A bounded buffer actor class in ACT++.

Page 73: Language Design Rationale and Semantic Framework for

58 Classification of Existing Languages

Operationget illustrates the use of the primitivesreply andbecome. The next item in the

buffer is immediately returned to the caller by thereply statement, then the caller and the buffer

proceed in parallel. The buffer examines its internal state and chooses its replacement behavior.

The replacement behavior is specified by using thebecome primitive with the associated behav-

ior name.

The idea of behavior abstraction is interesting because it extends the data abstraction mech-

anism of sequential languages by including some information concerning the temporal aspects

of an object’s behavior. As a mechanism for selective acceptance of requests, it may be charac-

terized as a mechanism based on representation independent activation conditions. The condi-

tion for the acceptance of the request is that the object be in the appropriate abstract state spec-

ified by its current behavior. This is another interesting aspect of behavior abstraction that allows

it to be nicely combined with class inheritance. We will further discuss this issue in the next

chapter.

3.5.3 The Homogeneous Approach

ABCL/1

Objects in ABCL/1[92] are active entities that encapsulate a single thread of control. A variety

of message-passing constructs, including both one-way asynchronous message passing primi-

tives and higher level constructs, are provided for object interaction.

An object may be in one of the modes:dormant, active orwaiting. Objects are created and

remain in the dormant mode until they receive and start processing a message. While processing

a message an object is in the active mode. From the active mode it may go back to the dormant

or enter the waiting mode. An object goes from the active mode to dormant mode, when it has

finished processing a message and no further messages have arrived. It goes from the active

mode to the waiting mode when it has to wait to receive a message satisfying a particular con-

straint before it can do anything else.

Object interactions may have the form of remote procedure calls callednow type message

passing, asynchronous one-way message passing calledpast type message passing, and a form

called future type message passing. Future type message passing is a non-blocking variant of re-

mote procedure call where a special future variable is specified for storing the result to be re-

turned by the receiver. The sender may continue executing in parallel with the receiver and ob-

tain the result when needed by using this special variable. If the result is not available yet, the

sender is suspended. It is also possible for the sender to test if the result is available. Future type

Page 74: Language Design Rationale and Semantic Framework for

Chapter 3 59

message passing is similar to the CBox objects feature of ConcurrentSmalltalk[90]. The main

difference is that CBoxes are first class objects. So, for instance, a CBox object may be passed

to another object than the caller for receiving the result. This effect can not be achieved with fu-

ture type message passing since the future variable is only accessible to the caller.

Objects are defined in terms of their state and theirscript. The state of an object contains

the definitions of its permanent variables which can only be accessed from within the script. The

script specifies the messages that are accepted by the object and the actions to be executed upon

receipt of a message. The specification of an acceptable message consists of the specification of

the mode in which the message is acceptable, a message pattern, an optional reply destination,

and an optional constraint.

The reply destination may be saved and a reply may be sent later using a past type message.

This allows an object to decide when to process requests even if they were issued by now type

messages. Even if a now type message has been accepted by an object further messages may be

accepted and processed before replying to the first message.

Figure 3.5 A bounded buffer in ABCL/1

[ object buffer( state [ s = ( create-storage 3)] )( script

( => [:put aProduct](if (full? s) then

(select( => [:get]

!(fetch s))))

( store aProduct s )!"done" ; return "done" as an acknowledgment

)( => [:get]@R

(case (fetch s)(is :empty

(select(=> [:put aProduct] ; sent to the consumer

[R <= aProduct] ; confirmation to producer

!"done")))

( is aStoredProduct[ R <= aStoredProduct ]

))))) ]

Page 75: Language Design Rationale and Semantic Framework for

60 Classification of Existing Languages

Figure 3.5 shows a bounded buffer object that illustrates some of these features. In the dor-

mant mode the buffer accepts messages that match the message patterns:put aProduct and :get.

Accepting a:put message binds the variableaProduct to what follows:put in the message. When

a put message is accepted if the buffer is full it goes into waiting mode by executing theselect

statement. This allows the buffer object to wait until aget message is received. When aget mes-

sage arrives an item is removed from the store of the buffer and is sent to the object that sent the

get message, then the item to be put in the buffer is inserted in the storage and an acknowledg-

ment is sent to the sender ofput.

If a get message is accepted when the object is in the dormant mode the reply destination

for this message is bound to the variableR. If the buffer is empty the object enters the waiting

mode and waits for aput message. When aput message arrives the item contained in theput mes-

sage is immediately sent to the reply destination of theget message, saved in variableR, and an

acknowledgment is returned to the object that sent theput message.

The reply destination of a message is determined implicitly for now type messages and fu-

ture type messages. In general for past type message there is no reply destination since no reply

is expected, but it possible to explicitly specify a reply destination for past type messages. This

is very useful when an object wants to forward a request sent to it, with a now type message, to

another object.

Another interesting feature supported isexpress mode messages. A message sent in express

mode has the effect of interrupting processing of a message that was sent inordinary mode. After

the express message has been processed the object may choose between resuming its previous

activity or aborting it. This feature is very useful when there is a need to interrupt an object while

it is executing.

This feature could be simulated in languages that allow objects to peek at messages sent to

them. Still, it would be painful to program it explicitly. Every now and then the code of ordinary

messages should examine the message queue and take the appropriate action.

The usefulness of this feature is illustrated in [92]by an example of a team of problem solv-

ers working on a problem in parallel. When the first of them finds a solution it interrupts the oth-

ers by sending them a message in express mode.

To avoid arbitrary interleaving of the actions associated to messages, an object explicitly

specifies what messages may be received in express mode. Also, atomic blocks may be used for

making sure that certain sensitive blocks of code are executed atomically, i.e., they may not be

interrupted by express mode messages. ABCL/1 does not support classes or types of objects, but

Page 76: Language Design Rationale and Semantic Framework for

Chapter 3 61

it is possible to define generator objects that are used to create several objects from the same ob-

ject description. Figure 3.6 which shows an object that is used to create bounded buffer objects.

ABCL/R

ABCL/R [86] is a reflective extension to the language ABCL/1 discussed above. The system’s

reflective architecture is based on meta-objects. That is, each objectX has a meta-object,↑X

which models its structure and behavior. The meta-object is the object’scausally connected self

representation.The object may inquiry or modify itself by interacting with its meta-object, and

changes to the object’s state through execution in the object or by accessing the meta-object are

reflected to the meta-object and to the object respectively.

Each object has a default meta-object whose methods are triggered by events in the execu-

tion of the object such as the arrival of a message. These methods determine behavioral aspects

of the object such as the order that messages are accepted, what script is executed for what mes-

sage etc. As meta-objects are objects with their own meta-objects, the message acceptance be-

havior of an object may be modified dynamically by modifying through the meta-meta-object,

the meta-object’s methods that determine the object’s message acceptance behavior. Any mes-

sage acceptance and scheduling policy may be supported in this way by the appropriate redefi-

nition of the meta-object’s methods. A number of interesting examples of this use of meta-ob-

jects may be found in [86].

POOL-T and POOL2

In POOL-T [5] objects have a single thread of control which is activated when the object is cre-

ation and which executes the sequence of statements in the object’sbody. Communication and

synchronization takes place by remote procedure calls. An object may explicitly accept messag-

es by executing ananswer statement in its body that specifies a set of methods.A message asso-

ciated with one of these methods is accepted and the method is executed. The caller and receiver

Figure 3.6 A bounded buffer generator in ABCL/1

[ object create-buffers( script ( => :new

![ object...state and script as in Figure 3.5

])

)]

Page 77: Language Design Rationale and Semantic Framework for

62 Classification of Existing Languages

synchronize during the execution of the method in a extended rendez-vous fashion. The caller is

blocked until the method executes areturn statement. Methods may also have a post-processing

section that is executed after the method has returned. This is useful if there are statements which

logically belong to the method but do not contribute in the computation of the result. There is

also aselect statement, like in Ada, that allows messages to be accepted conditionally. For ob-

jects that do not specify a body a default one is assumed which cyclically executes an answer

statement for accepting any message sent to the object.

The language POOL2 suppresses the select statement and provides a non-blocking variant

of remote procedure call. However, no support is provided for obtaining the result computed by

such a non-blocking method invocation.

Languages in the POOL family also support another notion of module than objects which

is called a Unit and is similar to an Adapackage. Units may define and exportroutines whose

execution may take place concurrently, so we could say that units are concurrent objects. How-

ever, Units are not first class objects in the sense that they may not be passed as arguments and

may not be created dynamically.

POOL-T and POOL2 do not support inheritance. The reason is that it was not clear how

inheritance interfered with subtyping and that there was no satisfactory way for inheriting the

object’s body or to add methods without having to modify it [3].

Inheritance is supported in POOL-I [7]which is the latest member to join the POOL family.

It is distinguished from subtyping which is based on signatures augmented with object proper-

ties.Considering inheritance as separate from subtyping eliminates certain problems [41] that

occur in languages where the two concepts are coupled, and provides the programmer with more

flexibility as the two features may used independently.

Object properties provide a form ofname type equivalenceallowing the programmer to en-

hance object types with semantic properties. An object type is associated with a set of identifiers

chosen by the programmer to describe behavioral properties of the type. A subtype, apart from

having a compatible signature, should also have a set of properties that contains that of its su-

pertype. However, as behavioral properties of objects cannot be checked by a compiler it is the

responsibility of the programer to use this feature consistently.

Hybrid

Hybrid [62] was discussed extensively in the previous chapter. Here we are just going to mention

how Hybrid’s concurrency features are related to the design space presented in this chapter.

Page 78: Language Design Rationale and Semantic Framework for

Chapter 3 63

Hybrid supports a homogenous object model, as all objects are considered as active server-

like entities and protection of their internal state is provided by default. Objects are internally

quasi-concurrent. Internal threads are created by accepting messages, and scheduling of threads

within an object is controlled by delegated calls.

Conditional acceptance of requests is supported by the delay queue mechanism which is a

form of conditional acceptance based on activation conditions that depend on the object’s inter-

nal state.

Object interaction takes place in a remote procedure call fashion. An asynchronous opera-

tion invocation mode is also supported for operations defined as reflexes. This is used for sup-

porting concurrent execution in the system rather than for object interaction.

SINA

Object interaction in SINA [81]takes place by remote procedure calls. Messages sent to objects

are stored in an interface queue. Each object has a system defined object manager that manages

the interface queue and selects messages to be processed by the object. The object manager of

an object O is denoted↑O and it supports the operationshold() andaccept(). These operations

have the effect of setting the object’s interface in thehold andaccept state respectively. In the

hold state no messages are processed by the object. They are instead delayed in its interface

queue until the object interface goes to the accept state.

In the accept state the object’s interface alternates between the sub-statesblocked andfree.

In the free state a message is removed from the interface queue, a process is created for process-

ing the message and the interface moves to the blocked state. No further messages are processed

while the interface is in the blocked state. The interface goes back to the free state when the pro-

cess that caused the interface to go in the blocked state terminates. With this scheme messages

are processed serially and at most one process can run within an object at a time. Adetach() prim-

itive offers the possibility to process messages concurrently. When the process that caused the

interface to go to the blocked state executes this primitive the interface of the object goes to the

free state. This allows another process to be created for processing, concurrently with the “de-

tached” process, the next message in the object’s interface queue.

Objects in SINA may be methods or data objects. Data objects may be primitive objects

such as integers or instances of user defined abstract data types. Methods are associated with a

process description (i.e. the code of the method). Each time a message is sent to a method object,

a process is created, according to the message acceptance rules described above, to execute the

Page 79: Language Design Rationale and Semantic Framework for

64 Classification of Existing Languages

process description with the formal parameters bound to the objects contained in the message.

Objects which are instances of abstract data types export a collection of method objects that may

be invoked by other objects. The invocation of such methods takes place by qualifying the meth-

od’s name by that of the invoked object. Invocation messages to exported methods are sent to

the object’s interface queue. Then, the object manager schedules the message for processing by

sending it to the queue of the invoked exported method object.

New object types are defined by grouping other data objects and methods together in a type

definition. A type definition specifies which objects (usually methods) are visible to other ob-

jects. This determines the type’s interface. Objects contained within a type definition may in-

voke thehold() andaccept() operations on object managers of other objects contained within the

type. This allows various forms of synchronization.

Although this model at first may appear extremely complex the resulting language is rather

simple. Type definitions resemble types or classes in other languages and method execution may

be understood as in other languages. Figure 3.7 illustrates this by the definition of a bounded

buffer type in SINA.

Figure 3.7 Bounded buffer in Sina

type buffer interface isbegin

method put( integer as item ) returns nil;method get() returns integer;

end;type buffer local isbegin

objects integer as itemcount, head, tail, buff[N];

initialbegin head := 0; tail := 0; itemcount := 0; ↑get.hold();end

methodsput:begin

itemcount := itemcount +1;if itemcount = N then ↑put.hold();buff[tail]:= item; tail := (tail+1) mod N;↑get.accept();return val;

end;

get: objects integer as val ;begin ... code for get ... end;

end;

Page 80: Language Design Rationale and Semantic Framework for

Chapter 3 65

The initial statement is a process description for a process that is executed at the creation of

an instance of this type. After this process has terminated the interface of the object is in the free

state and messages may be processed. The execution of↑get.hold() by this process sets the inter-

face of the method get to the hold state by invoking the operationhold() on its object manager.

The interface ofget is now in the hold state which means that messages sent toget will be queued

until its interface goes to the accept state. The interface ofput is in the accept state so messages

sent toput may be processed.

When a message is sent toput, a process is created that executes the code of the methodput.

The code of this method appends an item to the buffer and if the buffer becomes full it sets the

interface ofput at the hold state so that no more messages will be processed byput, then it sets

the interface ofget to the accept state by invoking the accept operation on its object manager.

After the execution of the method terminates, messages toget may be processed.

With respect to our classification SINA adopts the homogenous object model since, by de-

fault, objects process messages sequentially and are thus protected from concurrent execution.

Objects are internally concurrent. The creation of internally concurrent threads is initiated by ex-

ternal messages and is controlled by the object with thedetach statement and the use ofaccept

andhold primitives on the object managers of exported methods. Conditional acceptance of re-

quests is supported by thehold primitive whose use for conditional acceptance of requests is sim-

ilar to Hybrid’s delay queues. This is a restricted form of conditional acceptance since the con-

dition, which is that the interface of the requested method be in the accept state, may not take

into account the invocation’s arguments.

3.6 Summary

Table 1 summarizes the nature of object threads for each language discussed in 3.5. Note that

for ACT++ and PAL, although multiple threads may execute within an object, no synchroniza-

tion problems can occur since they access different versions of the object’s state. In the case of

ACT++ the programmer specifies through the use of abecome primitive, inspired from the actor

model, when the new version of the object’s state is created. In PAL the management of object

state versions and concurrent execution is completely transparent to the programmer.

Table 2 shows how threads are created within objects. This may be either by the acceptance

of messages or by the execution of special statement. For languages where objects are single-

threaded neither choices are available so the corresponding rows are left blank. In these languag-

Page 81: Language Design Rationale and Semantic Framework for

66 Summary

es the object’s thread is created at the object’s creation time and no further threads may be cre-

ated within objects.

Table 1 Intra object concurrency

Language Sequential Concurrent Quasi-Concurrent

ABCL/1 √ABCL/R √ACT++ √ConcurrentSmalltalk √Eiffel// √Emerald √Guide √Hybrid √PAL √POOL-T √POOL2 √Sina √Smalltalk-80 √SR √

Table 2 Creation of threads within objects

Language Execution message acceptanceof a statement

ABCL/1

ABCL/R

ACT++ √ConcurrentSmalltalk √ √Eiffel//

Emerald √Guide √ √Hybrid √PAL √ √POOL-T

POOL2

Sina √Smalltalk-80 √ √SR √ √

Page 82: Language Design Rationale and Semantic Framework for

Chapter 3 67

Table 3 lists the mechanisms that are available for conditional acceptance of requests. It

should be noted that for languages that have an orthogonal object model unconditional accep-

tance is the default. This is however not listed in the table since this concerns object models and

here we are concerned with the mechanisms that are available for conditional acceptance of re-

quests.

Table 3 Request Acceptance

Language Unconditional Explicit activation reflectiveconditions computation

ABCL/1 √ABCL/R √ACT++ √ConcurrentSmalltalk √Eiffel// √Emerald √Guide √Hybrid √PAL √POOL-T √POOL2 √Sina √Smalltalk-80 √SR √

Page 83: Language Design Rationale and Semantic Framework for

68 Summary

Page 84: Language Design Rationale and Semantic Framework for

CHAPTER 4

Comparing the Design Alternativeswith Respect to Software Reuse

In the previous chapter we have shown a variety of ways in which concurrency features may be

combined with object-oriented ones. Although all these may be equally powerful for the con-

struction of concurrent programs, in this chapter we show that they are not equally successful in

drawing the benefits of object-oriented programming for software development. We show that

certain feature combinations do not adequately support object-oriented programming because of

the interference of features and identify a set of useful combinations of language design choices

that achieve a successful integration of object-oriented and concurrent programming concepts.

In order to evaluate the various design choices with respect to their support for OO pro-

gramming and software reuse, we formulate a number of requirements which express the inte-

gration of OO and concurrent programming concepts. The main idea behind these requirements

is that the support for concurrency in an OO language should not diminish the expected advan-

tages of OO features for software development. For instance, encapsulation should still protect

the internal state of objects from surrounding objects and it should still be possible to insulate

objects’ clients from implementation choices. This should make it possible to change the imple-

mentations without affecting an object’s clients provided that the interfaces are maintained and

that changes are, in some sense, behaviorally compatible.

The various design choices are evaluated by developing appropriate examples and consid-

ering application development scenarios illustrating that certain design choices fail to satisfy our

requirements.

Page 85: Language Design Rationale and Semantic Framework for

Language Design Requirements for Reusability70

The discussion in this chapter assumes an intuitive understanding of behavior compatibility

for objects in the sense that two objects are behaviorally compatible if one may be used in the

place of the other. However, a notion of behavior compatibility for active objects that may ac-

cept requests concurrently, delay requests or only accept requests in a certain order is not easy

to define. This issue, which is not addressed in this chapter, is further discussed in the two fol-

lowing chapters.

We first start by presenting in 4.1our requirements for a satisfactory integration of concur-

rency and OO features. Then we present an example application and propose a number of reuse

scenarios. In 4.2.2 we explore the design space presented in the previous chapter and illustrate

using the example the design choices that fail to satisfy our requirements. Finally, in 4.6 we sum-

marize our observations and make some comments on the approach used in this chapter for eval-

uating the design of COOPLs.

4.1 Language Design Requirements for Reusability

The following requirements are motivated by the principle that reusable object classes should

make minimal assumptions about the behavior of applications that will use them.

1. Mutual Exclusion-Protecting the Objects’ State: The internal state of objects should be

automatically protected from concurrent invocations so that it will be possible to reuse

existing objects in concurrent applications without modification.

2. Request Scheduling Transparency:An object should be able to delay the servicing of

requests based on its current state and on the nature of the request. This should be accom-

plished in a way that is transparent to the client. Solutions that require the cooperation of

the client are not acceptable from the point of view of reusability since the client then

cannot be written in a generic fashion.

3. Internal Concurrency: The concurrency constructs should allow for the implementation

of objects that service several requests in parallel or that make use of parallelism in their

implementation for increased execution speed in the processing of a single request. This

could be done either by supporting concurrent threads within an object or by implement-

ing an object as a collection of concurrently executing objects. Whatever approach is

chosen it is important that internal concurrency be transparent to the object’s clients so

that sequential implementations of objects may be replaced by parallel ones.

4. Reply Scheduling Transparency:A client should not be forced to wait until the serving

object replies. In the mean time it may itself accept further requests or call other objects

Page 86: Language Design Rationale and Semantic Framework for

Chapter 4 71

in parallel. It may even want that replies be directly sent to a proxy. Request scheduling

by the client should not require the cooperation of the server since this would limit the

ability to combine independently developed clients and servers.

5. Compositionality and Incremental Modification:Existing object classes should be re-

usable within new contexts without modification. Additionally, mechanisms for incre-

mental modification of classes such as inheritance must be designed with special consid-

eration given to concurrency to allow existing code to cooperate gracefully with modifi-

cations and extensions [41],[80].

4.2 Comparing the Language Design Choices

4.2.1 An Example Application

In order to compare the design choices and their combinations with respect to the reuse require-

ments, we shall refer to an instance of a “generic” concurrent program structure: theadministra-

tor inspired by [32]. The administrator is an object that uses a collection of “worker” objects to

service requests. An administrator application consists of four main kinds of components. The

clients issue requests to the administrator and get back results. Theadministrator accepts re-

quests from multiple concurrent clients and decomposes them into a number of subrequests. The

workload manager maintains the status of workers and pending requests.Workers handle the

subrequests and reply to the administrator. The administrator collects the intermediate replies

and computes the final results to be returned to clients.

The administrator is a very general framework for structuring concurrent applications. For

example, workers may be very specialized resources or they may be general-purpose compute

servers. The workload manager may seek to maximize parallelism by load balancing or it may

allocate jobs to workers based on their individual capabilities.

clients

administrator

workersworkload manager

Page 87: Language Design Rationale and Semantic Framework for

Comparing the Language Design Choices72

The components described above identify functionally distinct parts of the application that

could have been developed independently and reused as indicated above to construct a new ap-

plication.These components do not have to be implemented as single objects and indeed as we

see later depending on the constructs provided by certain languages several objects will be nec-

essary for realizing the desired functionality. However, it should be possible to modify the im-

plementation of the above components without affecting the rest as if they were single objects.

The following points relate the language design requirements, presented in 4.1, to reuse is-

sues in the case of the example application:

• Mutual Exclusion: (i) workload manager reuse – the workload manager must be protected

from concurrent requests by the administrator.There may be cases where the administrator

does not invoke the workload manager concurrently. Although in such cases no protection is

needed workload managers that are not protected could not be reused in different concurrent

implementations of the administrator. In such a concurrent implementation the administrator

may use a collection of proxies that may invoke the workload manager concurrently; (ii)

worker reuse – workers should similarly be protected so that arbitrary objects may be used as

workers with various implementations of the administrator including concurrent ones;

• Request Scheduling Transparency: (iii) Genericity of clients, reusing the administrator with

different clients– the administrator must be able to interleave (or delay) multiple client re-

quests, but the client should not be required to take special action. In fact it should be possible

to implement any object as an administrator and it should not matter to the object’s clients if

the serving object happens to be implemented as an administrator;

• Internal Concurrency: (iv) client/worker reuse – the administrator should be open to concur-

rent implementation (possibly using proxies) without constraining the interface of either cli-

ents or workers;

• Reply Scheduling Transparency: (v) worker reuse – it must be possible for the administrator

to issue requests to workers concurrently and to receive their replies when it chooses without

special action by workers;

• Compositionality: (vi) administrator reuse – the administrator should be programmed in such

a way that its code may be easily reused for slightly different cases. This could be done by

modifying only some parts of the administrators implementation (parameterization, inherit-

ance, or other techniques may be appropriate).

There are other aspects of language design, apart from the concurrency features, that affect

the creation and use of reusable administrator applications, such as the support for generic or pa-

Page 88: Language Design Rationale and Semantic Framework for

Chapter 4 73

rametrized classes and the support for dynamic binding. In our discussion however we concen-

trate on issues that are more specific to the concurrency features of languages and ignore those

issues which would also arise in sequential languages.

4.2.2 Exploring the Language Design Space

In order to explore and evaluate the COOPL design choices we have selected, we shall consider

in turn object models, client/server interaction and internal concurrency, administrator reusabil-

ity. Throughout, we shall refer to the reusability requirements of 4.1 and we will make use of the

administrator example to illustrate specific points.

4.3 Concurrent Object Models

By the requirement of mutual exclusion, we can immediately discount the orthogonal object

model as it provides no default protection for objects in the presence of concurrent requests. The

reusability of workers and workload managers is clearly enhanced if they will function correctly

independently of assumptions of sequential access.

The heterogeneous model is similarly defective since one must explicitly distinguish be-

tween active and passive objects. A generic administrator would be less reusable if it would have

to distinguish between active and passive workers. Similarly worker reusability is weakened if

we can have different kinds of workers.

Thehomogeneous object model is the most reasonable choice with respect to reusability.

No distinction is made between active and passive objects.

Note that it is not clear whether the performance gains one might expect of a heterogenous

model are realizable since they depend on the programmer’s (static) assignment of objects to ac-

tive or passive classes. With a homogeneous approach, the compiler could conceivably make

such decisions based on local consideration – whether a component is shared by other concur-

rently executing objects is application specific and should be independent of the object type.

4.4 Thread Structure and Object Interaction Mechanisms

Here we examine how the choice of constructs for object interaction coupled with the thread

structure of objects affect the reuse that may be achieved in the construction of administrator ap-

plications. We first start by considering sequential objects coupled with an RPC communication

mechanism since this is the closest to sequential languages. Then, we consider in turn the solu-

tions that are provided by maintaining sequential objects combined with non RPC communica-

Page 89: Language Design Rationale and Semantic Framework for

Thread Structure and Object Interaction Mechanisms74

tion mechanisms and non-sequential object approaches. For each combination of features we

sketch the possible ways to implement administrator applications and examine to what extent

specific feature combinations satisfy or fail to satisfy the reuse requirements.

4.4.1 Sequential Objects

RPC

If we provide an object model where objects have a single thread of control and RPC as the only

communication mechanism, we quickly discover that this is not enough to satisfy the require-

ments of the administrator. In particular, a sequential RPC administrator will not be able to in-

terleave multiple clients’ requests as it will be forced to reply to a client before it can accept an-

other request. The only “solution” under this assumption requires the cooperation of the client,

for example: the administrator returns the name of a “request handler” proxy to the client, which

the client must call to obtain the result. In this way the administrator is immediately free to ac-

cept new requests after returning the name of the request handler. Such an approach is however

incompatible with the requirement on request scheduling transparency since scheduling of re-

quests by the administrator is not transparent to its clients.

Consider for instance that we would like to replace the sequential implementation of an ex-

isting object class by a parallel implementation where instances of the class act as administrators

for a collection of appropriate worker objects. In accord with our requirements we would like to

take advantage of encapsulation and data abstraction to replace the old implementation without

having to modify the programs that used it. This however is not possible since, as discussed

above, in order to be able to process client requests concurrently an object, implemented as an

administrator, has to have a different interface than an object having a sequential implementa-

tion.

The sequential RPC combination also provides limited support for reply scheduling by the

administrator. If the administrator invokes workers directly using RPC, its single thread will get

blocked until the invoked worker computes the result and returns the reply. This disallows the

administrator to invoke several workers in parallel or accept further client requests while a work-

er computes the result and receive the workers’ replies at a later time.

The limitation of the sequential RPC combination for reply scheduling can be overcome by

the use of “courier” proxies used by the administrator to invoke workers. Each time the admin-

istrator needs to invoke a worker it creates an appropriate courier proxy that will invoke the

worker instead. For getting a worker’s reply the administrator could invoke a method of the cor-

Page 90: Language Design Rationale and Semantic Framework for

Chapter 4 75

responding courier or alternatively the courier could call an administrator’s method when the re-

ply becomes available.

The former alternative has the disadvantage that the administrator may get blocked if it in-

vokes the courier too early. This may never occur with the latter approach. However, the admin-

istrator has to manage local queues for replies that are sent to it and that it can not use immedi-

ately. Furthermore, each time a reply is returned it should check whether all the replies needed

so far for handling a client’s request are available so that it may proceed with the client’s request.

It would also be possible to have the workers cooperate with the administrator so that it

does not get blocked when invoking them. We have not considered such solutions as they require

that workers be coded specially to match the administrator’s needs which is incompatible with

our requirement, concerning request scheduling transparency, that any object could be used as a

worker.

We must either relax the sequentially constraint or the strict RPC protocol. The possibilities

are: (i) one-way message passing, (ii) explicit request/reply scheduling primitives (with or with-

out proxies), and (iii) internal concurrency.

One-Way Message Passing

An extreme solution in the direction of relaxing RPC is to support one-way synchronous or asyn-

chronous message passing. In this case the administrator is free to accept messages and reply to

them in the order it likes. One-way message passing has however some disadvantages.

A concurrent client may issue several requests to the administrator before it gets a reply. In

this case it is important for the client to know which reply corresponds to which request. Are

replies returned in the same order as requests? In the case of synchronous message passing an

additional difficulty is that the administrator may get blocked when it sends the reply until the

client is willing to accept it. Requiring the client to accept the reply imposes additional require-

ments on the client and makes reuse more difficult. Either a different mechanism has to be sup-

ported for sending replies or proxies have to be created.

One-way message passing is also inconvenient for coping with the interaction between the

administrator and worker objects. A difficulty with using one-way messages is getting the re-

plies from workers. As there are several workers that are invoked in parallel and potentially con-

current invocations of single worker it is difficult for the administrator to tell which reply is as-

sociated with which request.

Page 91: Language Design Rationale and Semantic Framework for

Thread Structure and Object Interaction Mechanisms76

A solution to this problem is to create a proxy for each request. The proxy would carry out

the request and then send a message to the administrator containing the worker’s reply plus some

extra information used for identifying the request. As with sequential RPC the administrator will

also have to manage local queues for partially completed requests.

Build-in Support for Courier Proxies

The administrator implementations described above made use of proxy objects for carrying out

requests and for storing replies. In the case of a sequential RPC combination such proxies were

necessary for allowing the administrator to call workers without getting blocked. In the case of

one-way message passing, proxies were still necessary for allowing requests to be paired with

replies.

Although proxies are a general programming approach it is cumbersome to program and

use them explicitly. In fact unless the language supports classes with type parameters and a flex-

ible manipulation of method names, a new proxy class would have to be defined for each differ-

ent worker class in an administrator application.

Future variables in ABCL/1[92], theprocess type in PAL[13] and CBox objects in Con-

currentSmalltalk[90] provide functionality which is somewhat similar to the courier proxies that

were used by the administrator to call workers. These mechanisms could be used by the admin-

istrator to call workers without getting blocked and for collecting worker replies at a later time.

The advantage of these mechanisms over program-defined proxies is that they can be used

for calling workers of any class. Future variables, however, are not first class objects and so are

not as flexible. For instance, a future variable cannot be sent in a message allowing a different

object than the one that made the request to receive the reply.

A difficulty with build-in proxies is that the administrator may at some point in time have

to get blocked and wait for a further client request or the reply to a previous worker request. Un-

less a powerful synchronization mechanism that allows the administrator to wait on either of

these events the administrator may get blocked to obtain a reply/request that is not available and

thus ignores other requests/replies. This problem could be circumvented either by polling if a

non-blocking request acceptance mechanism is supported or by additional, explicitly pro-

grammed, proxies that would return the replies by invoking some administrator’s operation es-

pecially provided for that purpose. This way a synchronization mechanism for selectively ac-

cepting requests would allow the administrator to be woken up either for receiving the results of

a previous requests or for accepting new requests.

Page 92: Language Design Rationale and Semantic Framework for

Chapter 4 77

Still, the administrator’s code may get quite involved. If there is no way to prevent being

woken up by messages containing client requests or worker replies that cannot be used right

away, local message queues will have to be managed by the administrator. So, it appears that

build-in proxies combined with single thread objects provide limited support for reply schedul-

ing by the administrator since one should again rely on the use of explicitly programmed proxies.

More Flexible Request/Reply Mechanisms

It is also possible to relax the RPC style of communication without going all the way to support

one-way message passing as the main communication primitive. This has the advantage that it

is possible to present an RPC interface to clients and, at the same time, obtain more flexibility

for processing requests by the administrator. This possibility is illustrated by ABCL/1[92] which

permits the pairing of RPC interface at the client side with one way asynchronous message pass-

ing at the administrator’s side. Moreover the reply message does not have to be sent by the ad-

ministrator object. This provides even more flexibility in the way that the administrator may

handle requests since the replies may be directly returned to the client by proxies. The following

segment of code shows how this is accomplished.

The RPC call at the client side looks like:

result := [ administrator <== :someRequest arg1 ... argn] ...

A message is sent to the administrator to execute the requestsomeRequest with argumentsarg1,

... ,argn. The client is blocked until the reply to the request is returned and the result is stored in

the client’s local variableresult.

At the administrator’s side the client’s request is accepted by matching the message pattern:

(=> :someRequest arg1 ... argn @ whereToReply.... actions executed in response to this request ... )

When the administrator accepts this request, the arguments are made available in the local

variablesarg1,...,argn and thereply destination of the request in the local variablewhereToReply.

The reply destination may be used as the target of a “past type,” i.e. asynchronous, message for

returning the reply to the client. As a reply destination may also be passed around in messages

it is possible for another object to send the reply message to the client. This action would look

like:

[ whereToReply <== result ]

wherewhereToReply is a local variable containing the reply destination, obtained by the message

acceptance statement shown above, andresult is the result to the client’s request.

Page 93: Language Design Rationale and Semantic Framework for

Thread Structure and Object Interaction Mechanisms78

Another interesting way of using the possibility to combine one-way message passing with

RPC is for flexible reply scheduling by the administrator. In the previous section, on build-in

proxies, we mentioned that a difficulty was that the administrator should be able to wait for ac-

cepting both returned replies and further requests. A way to circumvent this problem was to use

explicitly programmed proxies that would return results by invoking some operation provided

by the administrator. In this way replies were returned by requests so that a request acceptance

mechanism was sufficient for allowing the administrator to wait for both requests and replies. A

different approach is possible by pairing one-way messages to the RPC interface supported by

workers. With this approach the administrator may use a past type message, with itself as reply

destination, for calling the workers which present an rpc interface. The replies from the workers

can then be received by the administrator as any past-type message request. This allows the ad-

ministrator to use the message acceptance mechanism for receiving both requests and replies.

This approach has however some of the drawbacks of one-way message passing: Some ex-

tra work is needed in order to find out which reply message is related to what request and also

that the administrator has to manage queues for replies that may not be used immediately.

4.4.2 Multi-threaded Objects

Another way for allowing the administrator to service several concurrent requests is by support-

ing multiple concurrent or quasi-concurrent threads. A separate concurrent thread may now be

used for handling each client request. However, depending on the mechanisms provided for

thread creation and scheduling it may still be necessary to resort to the solutions discussed pre-

viously in order to achieve a satisfactory level of concurrency in the processing of client re-

quests.

We consider in turn quasi-concurrent and concurrent approaches and examine the support

provided by the thread creation and scheduling mechanisms for programming administrators.

Quasi-Concurrent Approaches

A traditional example of “objects” with quasi-concurrent thread structure is provided by moni-

tors [38][16]. However, monitors present some well known difficulties such as “nested monitor

calls” and unduly constrain parallelism [52][72][15] when used as the main modular units of

concurrent programs. These limitations are due to some extent to the quasi-concurrent structure

of threads. However, an approach based on monitors would also constrain concurrency among

different objects because of its limited support for reply scheduling. Assuming that the admin-

istrator is a monitor, then when calling a worker the monitor would remain blocked until the in-

Page 94: Language Design Rationale and Semantic Framework for

Chapter 4 79

voked operation would return. This situation calledremote delay[49] makes it impossible for the

administrator to accept further client requests or to call a second worker.

Consequently, certain object-oriented languages have adopted more flexible variations.

For example, Emerald [14] uses monitors as defined in [38]. However, not all operations of an

object have to be declared as monitor procedures and also several independent monitors may be

used in the implementation of an object.Lock blocks andwait queues in Trellis/Owl[60] also

allow for more flexible implementation schemes than if objects were identified to monitors.

With this approach however objects in these languages are not quasi-concurrent anymore.

The restricted support for concurrency among objects by monitors is not due to the quasi-

concurrent structure of objects, but rather to the limited flexibility for reply scheduling. This is

illustrated by the second quasi-concurrent approach we examine which by providing a more

flexible reply scheduling scheme does not restrict concurrency among objects.

Hybrid[62] is another language which adopts a quasi-concurrent thread structure for ob-

jects. However, in contrast to monitors the delegated call mechanism, discussed in detail in

chapter 2, provides a more flexible reply scheduling approach that does not restrain concurrency

among objects. The administrator may use the delegated call mechanism to invoke workers. In

such a case a new thread may be activated in the administrator for processing another client re-

quest in the meantime.

The delegated call mechanism is satisfactory for allowing the administrator to accept fur-

ther client requests while a worker is executing a previous request providing thus support for

concurrency among several client requests. However, it is of no help for allowing several work-

ers to execute in parallel for a single client request.

This may only be done by using proxies for invoking the workers or by a construct for spec-

ifying the creation of a new quasi-concurrent thread. Such a construct was supported in the orig-

inal design of Hybrid. The newly created quasi-concurrent threads would resume each other by

using delegated calls. This construct was not included in the prototype because it substantially

increased the complexity of the rules for message acceptance.

Concurrent Approaches

With concurrent threads it is straightforward to process several client requests concurrently by

creating a new thread for processing each client request. Provided that satisfactory mechanisms

are supported for constraining the creation and activation of concurrent threads this does not

cause the mutual exclusion problems of languages with an orthogonal object model. The con-

Page 95: Language Design Rationale and Semantic Framework for

Compositionality and Finer Grain Reuse80

current execution that may take place is explicitly specified by the programmer and the scope of

the potential interference of the concurrent threads is restricted to the state of a single object.

Provided that there is some way to suspend the execution of a concurrent thread or avoid

its creation, languages that support concurrent threads provide adequate support for request

scheduling and for internal concurrency to the extent that several client requests may be pro-

cessed concurrently.

A different issue however that is not necessarily addressed by the support for concurrent

threads is the possibility to use concurrency for processing a single request. Unless the creation

of multiple threads can be initiated by the object, the support for reply scheduling of concurrent

threads is not sufficient for processing a request in parallel.

For example the language SINA [81] makes it possible to use several concurrent threads

within an object for processing requests; there is no direct means, however, for one of these

threads to create more threads for calling the worker objects in parallel. This is done indirectly

by creating a courier proxy, as described previously. It is therefore not necessarily redundant to

support both multiple threads and non-blocking communication primitives.

A satisfactory way for calling workers in parallel without using proxies or asynchronous

message passing is to support a construct by which more threads may be created in the object.

In this case a worker can be called by each of these threads in an RPC fashion. With quasi-con-

current threads, a call to a worker should trigger the execution of another thread. Such constructs

are provided in the original design of Hybrid[62] and in SR[10]. Hybrid’s construct was dis-

cussed above. In SR the code segment of the administrator that is used for issuing requests to

workers in parallel would look like this:

. co result1 := w1.doWork(...) -> loadManager.terminated(w1)// result2 := w2.doWork(...) -> loadManager.terminated(w2)ocglobalResult := computResult(result1,result2);...

4.5 Compositionality and Finer Grain Reuse

Our evaluation of language design choices focused on the support provided for developing re-

usable objects and for defining new object classes in a way that makes it easy to reuse objects of

existing classes. Class inheritance is another way for supporting reuse at a finer grain than whole

objects. However, it is hard to take advantage of inheritance in COOPLs because, as we dis-

Page 96: Language Design Rationale and Semantic Framework for

Chapter 4 81

cussed in chapter 2 and as it was pointed out by other researchers [4][41][80], it interferes with

the concurrency constructs and encapsulation.

The design of COOPLs that make it possible to use inheritance is a research area in its own

right and it is a open research problem whether it is possible to design languages that take ad-

vantage of class inheritance and that satisfy our other requirements at the same time. Below we

will summarize some recent proposals for taking advantage of class inheritance in COOPLs and

comment on the support they provide for addressing our other requirements.

Interference between existing code to be reused (e.g., superclasses) and incremental mod-

ifications (e.g., subclass extensions) is due to (i) the difficulty of the additional code to synchro-

nize with the existing code and (ii) the difficulty of the existing synchronization code to be open

to modifications yet to be defined.

Taking as a criterion for the design of the synchronization mechanisms that the addition of

a new method by a subclass should not cause the redefinition of inherited methods, Kafura and

Lee [41] and Tomlinson and Singh [80] proposed independently two approaches which have in

common that the conditions for the synchronization of method execution do not refer directly to

the object’s instance variables and method names. They are instead expressed, indirectly,

throughabstract states andenabled sets, respectively, that may be redefined in a subclass in or-

der to account for the methods added by the subclass.

Although these approaches work well for the examples presented in [41] and [80], Matsuo-

ka et al. [55] showed, by an example, where all of the inherited methods had to be redefined in

a subclass, that this is not so in general. Also, the concurrency mechanisms proposed in both

these proposals do not adequately support reply scheduling. The proposal of Kafura and Lee is

also weak for request scheduling since activation conditions may not depend on message con-

tents.

Neusius [61] identifies the problem of combining inheritance and synchronization as: “The

dependency of the method specification and the synchronization protocol of an object is the

weak point that makes reuse and extensibility so difficult.” He proposes an approach where all

actions for specifying the synchronization of method execution are specified, separately from

the code of method, inmatching actions, pre-actions, post-actions associated with each method.

We agree with the above statement, however, in his approach, as in most work in the area

of “inheritance and concurrency,” the dependency of method specification with the synchroni-

zation protocol of an object seems to be understood in a rather narrow sense. That is, most of

this work seems to admit as a postulate that the dependencies, and the difficulties in reusing and

Page 97: Language Design Rationale and Semantic Framework for

Conclusions and Summary82

extending the code of concurrent objects, will vanish if methods do not contain actions to, di-

rectly, synchronize their execution with that of other methods.

We believe that the dependency of method specification to the synchronization protocol of

an object is more deeply rooted. Consider for example a synchronization protocol that specifies

what methods or groups of methods may be executed concurrently without violating the integ-

rity of an object’s state. Clearly, if the code of some method is changed, so that it uses some more

instance variables, the synchronization protocol should also be revised to ensure mutual exclu-

sion with respect to the execution of other methods. Although the code of the other methods will

not have to be modified it will be necessary to modify the synchronization protocol, so the de-

pendencies still exist.

It would be interesting to investigate how to combine the approach proposed by Neusius

with other concurrency constructs so that it adequately addresses all of our requirements. How-

ever, as it is the case with other approaches for supporting inheritance in COOPLs, it is not easy

to tell on the basis of a couple of examples whether the approach allows inheritance to be used

effectively in concurrent object-oriented programs.

4.6 Conclusions and Summary

We can make the following observations concerning our exploration of reuse issues:

• Homogeneous object models promote reuse: concurrent applications can safely reuse objects

developed for sequential applications; efficiency need not be sacrificed.

• Sequential objects with strict RPC are inadequate: request scheduling and internal concurren-

cy can only be implemented by sacrificing the RPC interface; the solution is to either support

concurrent threads or to relax the strict RPC protocol.

• One-way message passing is expressive but undesirable: since higher-level request-reply pro-

tocols must be explicitly programmed, development and reuse of objects is potentially more

error-prone.

• Acceptance of concurrent requests is well-handled either by concurrent threads or by explicit

request/reply scheduling.

• Issuing concurrent requests is well-handled by one-way message passing, by proxies or by in-

ternal concurrency: the combination of both concurrent threads and non-blocking communi-

cation primitives may be appropriate for handling the separate issues of accepting and issuing

concurrent requests.

Page 98: Language Design Rationale and Semantic Framework for

Chapter 4 83

• Built-in proxies used bysequential objects with non-blocking request issuing mechanisms

provide adequate support for reply scheduling but are weak at combining reply and request

scheduling.

• Both concurrent objects and multi-object approaches are useful for internal concurrency:

These approaches for internal concurrency are both useful for different purposes. Concurrent

threads make it easy to implement objects that may service several concurrent requests that

do not modify the objects state. Multi-object approaches are interesting when the implemen-

tation of a new object class, with internal concurrency, may be realized by using several con-

currently executing instances of existing object classes.

The evaluation of the design of the concurrency features of COOPL with respect to their

support for an object-oriented programming style was focused on the reuse of objects across ap-

plications and the possibility to reuse applications with modified implementations or extended

versions of object classes.

Languages that fail to satisfy our requirements will make it difficult or in some cases im-

possible to take advantage of the above aspects of reuse. However, more is needed for effective-

ly taking advantage of reuse potential of languages providing mechanisms that address our re-

quirements in a satisfactory way. Two essential issues are:

• Methods for the development of objects and application frameworks that provide high

reuse potential paired with criteria for evaluating and comparing the reuse potential of

alternative design choices.

• Providing the information necessary for safely reusing objects and application frame-

works. This information should provide in an abstract, rigorous and concise way the

specification of the behavior of objects in order to capture the behavioral constraints and

dependencies among objects of generic application frameworks. The semantic frame-

work which is the subject of the next section provides rigorous notion of object behavior

so that it is possible to specify the behavior of objects and to express and verify behav-

ioral constraints.

Page 99: Language Design Rationale and Semantic Framework for
Page 100: Language Design Rationale and Semantic Framework for

CHAPTER 5

A Unifying Framework forProcess Calculus Semantics ofConcurrent Object-BasedLanguages and Features

As shown in the previous chapter the various language design approaches are not equally suc-

cessful in integrating concurrency with the other OO features mainly because of the interference

between features. Such “design flaws” are generally uncovered only after the languages have

been fully designed and, possibly, implemented, by appropriate examples illustrating the inter-

ference of features[41][68][75][80]. We believe that a more rigorous approach for describing the

semantics of features, examining their interactions and comparing the various design choices

would be more effective for a satisfactory integration of the features.

An approach for the semantic definition of a concurrent programming language is by trans-

lation of the language constructs to a process calculus. This approach has been used in [58] for

the definition of a simple concurrent programming language by translation to CCS and also in

[65][83][85], using CCS or other process calculi for defining the semantics of concurrent object-

based languages. There are, however, different ways to translate the constructs of a language to

a process calculus. These may vary in the amount of operational detail or may use completely

different approaches for the translation of language features. This makes it hard to compare dif-

ferent language designs and draw useful conclusions about the interaction of a language’s fea-

tures.

In order to use the “semantics by translation” approach for examining the interaction of lan-

guage features and for comparing language designs we propose a framework for the semantic

Page 101: Language Design Rationale and Semantic Framework for

86

definition of concurrent object-based languages by translation to CCS. This framework may be

used for the definition of the semantics of concurrent object-based languages that follow very

different approaches for object-based concurrency. For example, both languages that view ob-

jects as passive abstract data types and languages in which objects are considered as single

threaded message-passing processes can be accommodated. The proposed framework also sup-

ports class inheritance, for which, to our knowledge, no process-calculus semantic definition has

been given before.

The framework consists of the definition of a common base structure for the representation

of COOPL features, such as objects, messages, classes, methods and their synchronization, in

CCS. This structure is captured by the definition of a number of agents with agent parameters

that act as derived operators. These derived operators define a derived calculus on top of CCS

that more directly supports the description of semantics of COOPLs. The differences on lan-

guage design choices may be understood by variation of the definition of some of these opera-

tors. The underlying process calculus framework may be used for the analysis of the properties

of the operators that correspond to different language design choices.

Apart from supporting the rigorous description of the semantics of COOPL features this ap-

proach has the benefit that the meaning of an individual object is given as a CCS agent. This

provides us with a formal definition of object behavior and a notion of behavior equivalence in-

duced from the equivalence defined on CCS terms. It also makes it possible to use the underlying

formal, process calculus, framework for asserting and verifying properties of objects.

In section 1.1, we discuss our approach for capturing basic object-based features such as

object identifiers, messages, classes and instances in CCS. We assume knowledge of CCS and

the value-passing calculus used in [58]. We also use “functions” over agents which are ex-

pressed as definitions of agents with agent parameters as discussed in [58] chapter 9.

In section 1.2, we discuss how to map objects defined in object-oriented languages to CCS

agents in a way that essentially different approaches for combining objects and concurrency are

easily accommodated. We define a simple concurrent object based language named SCOOL and

give its semantics. In section 1.3, as an illustration of the suitability of the framework for lan-

guages following significantly different approaches, we present the semantics of a different ver-

sion of SCOOL.

In section 1.4 we extend the approach presented in the section 1.1 to include class inherit-

ance by defining object classes as agents that take agents as parameters. We extend the syntax

of SCOOL to include inheritance and give the semantics of the extensions.

Page 102: Language Design Rationale and Semantic Framework for

Chapter 5 87

In section 1.5 we discuss alternative approaches for developing such a semantic framework

and for defining the semantics of concurrent object-oriented languages. We also compare our

choice of using CCS to what could be done by using a process calculus such as theπ-calcu-

lus[59] which supports label-passing, or a higher order process calculus such as CHOCS[79].

We also briefly discuss possible extensions and refinements of the framework.

5.1 Basic Framework: objects, classes and messages

A program consists of the parallel composition of agents representing the classes defined in the

program, agents representing predefined classes such as integers and Booleans, and a “start-up”

agent that represents the “main program.”

Classes are represented by agents that receive at the portrequestNewc, wherec is the class’s

name, requests for creating a new instance and supply at the portnewidc a value representing the

object identifier of the new instance. Some values may also be supplied at the requestNew port

to initialize the new instance.

Object identifiers belong to the set whereClassis the set of class names in

the program. Objects interact atrequestid,m andreplyk ports. A request port indexed byid, which

belongs to the set of object identifiers, andm, which belongs to the set of method names, is used

to send a message to the object identified byid requesting it to execute itsm method. A sequence

of the identifiers of the argument objects as well as a valuek used to identify the invocation are

transmitted as values along a request port.

The reply ports are used for communicating the object identifier of an object representing

the reply to a request. The reply ports are indexed by invocation identifiersk. These are values

supplied by the “caller” to allow different invocations to be distinguished. The portreplyk is used

by a caller to receive the reply to the request identified byk.

The use of reply identifiers may vary largely depending on the interaction primitives pro-

vided by the language. For modelling one-way message passing where the notion of reply is not

supported, reply ports and thus reply identifiers would not be used. For modelling single thread-

ed objects communicating by rpc the invoker’s object identifier would do. However, for lan-

guages that support multi-threaded objects or asynchronous invocations the invoker’s object

identifier would not be sufficient to identify the invocation. To cope with all these cases we as-

sume that reply identifiers are integers generated at each invocation by a global reply identifier

agent. This provides a means to uniquely identify each invocation in the system.

Oid ℵ Class×=

Page 103: Language Design Rationale and Semantic Framework for

Basic Framework: objects, classes and messages88

The only object interaction mechanism discussed in this paper is remote procedure call.

However, the approach for identifying requests discussed above is adequate for modelling var-

ious ways of receiving replies to requests such asfuture variables in ABCL/1[92] and CBoxes

in ConcurrentSmalltalk[90].

5.1.1 The Structure of Class Agents

Agents representing classes will have a different structure depending on whether they corre-

spond to predefined object classes or program-defined classes expressed in an object-oriented

language.

5.1.1.1 Program-Defined Classes

The behavior of program-defined classes is described by the agent de-

fined below, which is parameterized by the class’s name and an agent ClassBeh that represents

the behavior of the class’s instances. The latter agent is obtained from the class definition ex-

pressed in a programming language and has two value parameters. These are bound at the cre-

ation of a new instance to a value representing the object identifier and sequence of values used

for initializing the instance. The way that agents that correspond to the behavior of instances are

obtained from a class definition is fully described in 1.2.2 for the example language SCOOL.

where

The definition of the agentClassis based on a family of agentsClk. Each of these agents

accepts at the port, requestNewname, a request for creating a new instance of the class, identified

by thename subscript, and receives inp a, possibly empty, sequence of values for initializing

the new instance. It outputs at the portnewIdname the value(k,name) which corresponds to the

object identifier of a new instance and then creates two new agents. The first of these agents rep-

resents the new instance and the second is the next agent,Clk+1, in the family of agents that will

handle the next instance creation request. The name subscript of the portsrequestNewname

and newIdname is the class name and is used to distinguish among requests directed to other

classes in a program.

Note the use of “=” in defining equations. For the definition of recursive agents we will use

either the recursion operator,fix, or recursive defining equations, choosing in each particular

case whichever is more convenient and produces a more readable result.

Class name ClassBeh,( )

Class name ClassBeh,( ) Cl0 name ClassBeh,( )=

Cln name ClassBeh,( ) requestNewname p( ) .newidname n name,( ) .=

ClassBeh n name,( ) p,( ) |Cln 1+ name ClassBeh,( )( )

Page 104: Language Design Rationale and Semantic Framework for

Chapter 5 89

5.1.1.2 Predefined Classes

Generally object-oriented languages support a number of predefined object classes such as inte-

gers and Booleans. These are expressed in our framework by agents representing predefined

classes, which are composed with the user-defined ones in a program. In contrast to program-

defined classes that are expressed in the syntax of a programming language, agents for prede-

fined classes are directly expressed as CCS agents. However, predefined classes and their in-

stances conform to the protocol for agents representing classes and instances described above.

In section 3 we define agents corresponding to predefined classes for semaphores, Booleans and

integers that are used for the semantic definition of our example language.

5.1.2 Remarks

The approach for modelling object interactions at fixed ports indexed by object identifiers is suf-

ficient to model dynamic interconnections among objects which take place in object-oriented

languages by the communication of object identifiers among objects. At the CCS level all pos-

sible interconnections between agents representing objects are set up beforehand and object

identifiers act as switches in this huge interconnection network. We have, so far, found this ap-

proach satisfactory for modelling objects and it appears to be less cumbersome for modelling

some language features than what could be accomplished with theπ-calculus[59] which directly

supports dynamic interconnections. This is further discussed in section 1.5.

5.1.3 The Structure of Program Defined Objects

In this section we describe the structure of agents that represent objects whose behaviors are ex-

pressed in an object-based language. The mapping from class definitions to such agents is fully

described in section 1.2.2 for an example language. The motivation for taking this approach for

representing objects is to easily accommodate different object models and features. This will be-

come clearer as we elaborate on these issues in later sections.

Agents representing objects are structured as an assembly of agents. Some of these agents

are obtained from the object’s class definition while others are proper to the language’s object

model. Objects in languages that take substantially different approaches for their object models

are accommodated by the appropriate definition of the language dependent components. The

structure of objects is given in figure 5.1 and the purpose of the different kinds of components

is explained below.

Page 105: Language Design Rationale and Semantic Framework for

Basic Framework: objects, classes and messages90

The Request Handler

This agent, defined below asRH, accepts requests, requestid,m(r,<v1,..,vn>) , for the execution

of one of the object’s methods identified bym. It creates anActivate agent, representing a pend-

ing request, which will interact with the appropriate method agent for the execution of the meth-

od. TheActivate agent has to wait for an signal from the method scheduler before

it interacts through acallm event with the method agent for executing the method.

This agent is very important for modelling inheritance in section 1.4.

Instance Variables

There is one such agent per instance variable. These agents are very similar to the agents used

for modelling variables in [58]. The main difference is that instead of storing integer and

Boolean values our variable agents store object identifiers. Also, our variable agents are defined

in such a way that they may be initialized at their creation.

The value (0,nil) standing for the identifier of the undefined object will be used to initialize

all non explicitly initialized variables. This object accepts any request sent to it and generates an

event indicating an error. This event could be used to model an exception handling mechanism,

however, exception handling will not be discussed any further.

requestid,m

replyk

Method Agents

Instance Variables

SELF

Request Handler

Method Scheduler

requestid’,m’

replyk’

Figure 5.1

activatem

RH id Meth,( ) fix X= requestid m, r v,( ). Activatem r v,( )|X( )m Meth∈∑( )=

Activatem r v,( ) activatem( ) .callm r v,( )=

VarV val( ) setV val'( ) .Var=V

val'( ) getVval.VarV val( )+

Page 106: Language Design Rationale and Semantic Framework for

Chapter 5 91

In order to restrict access to a variable and thus model local variables and encapsulation we

define the access sortACCV of a variable V in way analogous to that in [58] as

. Restriction byACCV renders the variableV local to the scope of the restric-

tion.

Method Agents

There is one such agent for each object method. These agents accept activation requests contain-

ing values for the method’s arguments, they create an agent representing the method’s body in

an environment where “local” variable agents hold the arguments of the method activation. This

way several activations of a method may take place concurrently.

This agent is parameterized by the method namem and an agentMBody. It repeatedly ac-

cepts invocations at the portcallm where invokers supply a sequence of valuesv1,..,vn represent-

ing object identifiers, denoted here asa, for the method’s arguments and a valuer which is used

to identify where to send the reply.MBodyis the agent that is obtained from the definition of the

method in the modelled programming language in the way shown in section 1.2.

The Method Scheduler

The purpose of this agent is to control the concurrent execution of methods. It interacts with the

Activate agents created by the request handler, imposing synchronization constraints on the ac-

tivation of methods. By varying the nature of synchronization constraints imposed by this agent

on the concurrent activation of methods we can accommodate significantly different object mod-

els. This agent will also interact with the execution of certain method statements. For example,

consider a scheduler that does not allow method executions to take place concurrently. Before

generating an to enable the execution of a method it has to be informed that the execu-

tion of the previous method is terminated. This may be done by a event that is gen-

erated by the last statement of the executing method or by a “return” statement.

For modelling the synchronization of method execution that takes place in some languages

more information needs to be exchanged between the method scheduler and the execution of

method statements. For instance, to model languages with synchronization mechanisms derived

from path expressions [58] it is necessary to know which method has terminated. This would

require that the terminate events would carry information about the method name. As such in-

formation is not required by the scheduler of the languages discussed in this paper we have not

included such information to simplify the presentation.

ACCv getv setv{ , }=

Method m Mbody,( ) fix( X= callm r a,( ).Mbody r a,( ) |X)=

activatem

terminate

Page 107: Language Design Rationale and Semantic Framework for

Defining SCOOL, a Simple Concurrent Object-Oriented Language92

The agentOrth defined below, is used for modelling languages with anorthogonal object

model where, as defined in chapter 3, objects are considered as passive abstract data types. Syn-

chronization of method execution in such languages is achieved within methods by the invoca-

tion of special objects as, for example, semaphores in Smalltalk-80 [34] or locks in Trellis/

Owl[60]. So, the schedulerOrth used to model objects in these languages does not impose any

synchronization constraints on the activation of an object‘s methods.

This scheduler agent is used in section 1.2 for defining the semantics of the language

SCOOL. In section 1.3 we discuss an alternative approach for method scheduling corresponding

to a different version of SCOOL.

Self

This agent operates as a “read-only variable” bound at object creation to the object’s identifier.

It is used by the object to find out about its own identity and class. This agent is used in the se-

mantics of languages where the pseudo variableself may be used for designating the object itself.

Its definition is:

Objects

Finally, an object is modelled by an agent defined as the concurrent composition of the above

agents and parameterized by its object identifier, which is used by the request handler for accept-

ing requests. Restriction is used to hide the events used for the interaction between the above

agents and eliminate the potential for interference with the events occurring in other objects.

5.2 DefiningSCOOL, a Simple Concurrent Object-Oriented Language

In this section we define a very simple object-oriented language for illustrating how the seman-

tics of various object-oriented features can be expressed in our framework. In later sections we

will extend the language by including more features and discuss how to accommodate them in

the basic framework.

5.2.1 Syntax and Informal Description ofSCOOL

The version of SCOOL discussed in this section does not support inheritance and takes an or-

thogonal approach for concurrency. The operations of objects are invoked in a remote procedure

Orth activatem.Orth terminate.Orth+m Meth∈∑=

Self id( ) getSelfid.Self id( )=

Page 108: Language Design Rationale and Semantic Framework for

Chapter 5 93

call fashion by concurrent threads. The synchronization of operation execution has to be

achieved by the judicious programming of object methods.

A program consists of a sequence of class declarations, variable declarations and a state-

ment representing the “main” program.

The creation of a new concurrent thread is expressed by thefork expression. This expres-

sion is parameterized by a statement which will be executed by a new concurrent thread. The

value of thefork expression is the object identifier of an instance of the predefined classprocess.

Process objects allow threads to be synchronized. By invoking thewait operation of a process

object the invoking thread is suspended until the thread corresponding to the process object ter-

minates. Another means for thread synchronization is provided by invoking theP andV opera-

tions of semaphore objects which are instances of the predefined classsema.

We assume that the language is statically typed. This simplifies the semantics since we do

not have to consider the eventuality that a requested operation is not supported by the invoked

object.

Apart from the predefined classesprocess andsema mentioned above, SCOOL also sup-

ports predefined classes for integers and Booleans with the operations that are commonly attrib-

uted to these object types in programming languages. We also assume the existence of a single

predefined instance representing the undefined object. This object, denoted bynil, accepts re-

quests for any method and generates an event representing an error.

The syntax for SCOOL’s expression and statements is listed below, whereE andS, possibly

indexed, stand for expressions and statements respectively.

Expressions

X whereX is a variable

self the value of the executing object’s identifier

n wheren = 0,1,2...

b whereb = true, false

nil denotes the undefined object

new C(E1,..,En) create an object of classC

E.m(E1,..,En) rpc invocation where m is a method name

E1 = E2 comparison of the object identifiers

fork S Create a new thread for executing S

Page 109: Language Design Rationale and Semantic Framework for

Defining SCOOL, a Simple Concurrent Object-Oriented Language94

Statements

X := E assignment

if E then S1 else S2 conditional

while E do S iteration

{ S} compound statement

S1; S2 sequential composition

skip no action

E. turn the expression E into a statement by discarding the result

return E return the value of E to the caller

Declarations

A declaration may be a variable declaration, a method declaration, a class declaration or a pro-

gram declaration

Decl ::= VarDecl + MethodDecl + ClassDecl + ProgramDecl

VarDecl ::= var X1:C,...Xn:C;

MethodDecl ::= method m (a1,..,an) { VarDecl S }

ClassDecl ::= Class C { VarDecl MethodDecl1...MethodDecln}

ProgramDecl ::= ClassDecl1 ....ClassDecln { VarDecl S }

5.2.2 Semantics

RequestIdGen is the agent used to generate identifiers for invocation requests. It is defined

as:

ProcClass, SemaClass, IntClass andBoolClass are the agents representing SCOOL’s pre-

defined object classes. These agents are defined in section 1.2.2.2.

Class Declarations

where

with

[[ ProgramDecl]] [[ ClassDecl1]] | ... | [[ ClassDecln]] | [[ VarDecl]] |=

RequestIdGen0( ) | [[ S]] | ProcClass| SemaClass| IntClass| BoolClass

RequestIdGen n( ) requestId n.RequestIdGen n 1+( )=

[[ class C { VarDecl MDecl1...MDecln } ]] Class C ClassBehaviorc,( )=

ClassBehaviorc id p,( ) Object id ms C( ) [[ VarDecl ]] | MethDecl, ,( )=

Page 110: Language Design Rationale and Semantic Framework for

Chapter 5 95

and

Where L is a function defined in [58] that gives the sort of an agent. ms is a function that gives

the set of method names of a class.

The agents Class, the request handler agentRH, Self and the method scheduler Orth were

discussed in section 1.1.

ClassBehavior is parameterized by two value parameters the second of which is not used

in the SCOOL example. This second parameterp is needed, in geneneral, to supply values for

initializing new instances of a class. However, as in SCOOL we provide no way for initializing

instances at their creation this parameter is ignored. Also, the expression listE1,...,En in an ex-

pression “new C(E1,...,En)”, used for creating an instance ofC, will be typically empty except in

the case of some of the predefined classes discussed in 1.2.2.2.

Variable Declarations

Method Declarations

where

if

and with

TheMethod agent was defined in section 1.2. The“Before Terminate” expression is used

to intercept the event generated by the last statement in the method body and inform the

method scheduler with a event that the execution of the method is completed. TheTer-

minate agent is defined as andBefore is a binary operator over agents, de-

fined in 1.2.2.1, that activates its right operand after the left one has generated a event.

MethDecl [[ MDecl ]] | ... | [[ MDecln ]]=

Object id M X, ,( ) RH id M,( ) |Orth M( ) |Self id( ) |X( )=

\ L Orth M( )( ) \ L Self id)( )( ) \ L X( )

[[ var V1: C1, ... ,Vn: Ck]] Varv10 nil,( ) | ... |Varvn

0 nil,( )=

[[ method m a1 ... an, ,( ) { VarDecl S} ]] Method m MethodBody,( )=

MethodBody r<v1 ... vn>, , ,( ) =

( Vara1v1( )| ... |Varan

vn( ) |Varv1

nil( )| ... |Varvknil( )| ( [[ S]] r( ) Before Terminate) )

\ ACCv1...ACCvk

\ ACCa1...ACCan

VarDecl var V1: C1 ... Vk: Ck,,=

nil 0 nil,( )=

done

terminate

Terminate terminate=

done

Page 111: Language Design Rationale and Semantic Framework for

Defining SCOOL, a Simple Concurrent Object-Oriented Language96

The event may also be generated directly by the return statement discussed in the

next section.

5.2.2.1 Expressions and Statements

The semantic description of SCOOL’s statements and expressions builds on the semantic de-

scription of the languageM0 given in [58]. However, apart from the fact that more statements

and expressions are introduced a slightly different approach has been taken for predefined ob-

jects and for the semantics of statements.

Objects such as integers and Booleans are handled in [58] by the semantics given to expres-

sions. Here, we represent integers and Booleans as predefined objects. This allows us to give the

semantics of expressions independently of whether they evaluate to objects of predefined or user

defined classes.

Another difference is that statements are mapped to parameterized agents. This is needed

because of the way that we define the semantics of the return statement and is further discussed

below.

Agents Representing Expressions

Expressions are mapped to agents that yield up the value of the expression at the port. The

combinatorInto defined below is used to allow an agent to refer to the value computed by an-

other agent representing an expression.

If Q is an agent expression where the variablex occurs free thenInto binds this variable to

the value computed byP.

The definition of this combinator is not exactly the same as that in [58]. There it is assumed

thatres is not in the sort ofQ,so the relabellingresis unnecessary. Here, as we do not make this

assumption, we have to relabelres to a labelb that we assume does not occur free in eitherP or

Q.

Statements and Sequential Composition

Agents that represent statements indicate their termination at the distinguished label. Se-

quential composition of two statements representing agents is expressed by the combinator

Beforedefined as:

terminate

res

P Into x( ) Q P b/ res[ ] | b x( ) .Q( ) \ b=

done

P Before Q P b/ done[ ] |b.Q( ) \ b=

Page 112: Language Design Rationale and Semantic Framework for

Chapter 5 97

We also define the agent Donewhich will be useful in the definition of the semantics of state-

ments as

Semantics of Expressions

,

where

The semantics of the fork expression whose informal semantics was discussed in 1.2 merits

some explanation. The execution of this expression creates an instance of the predefined class

process, defined in 1.2.2.2, and yields its id as the result of the expression. This id may be used

for invoking the wait operation of the process object which allows the invoker to be suspended

until the execution of the associated statement terminates. Then it creates an agent for executing

the forked statement as well as an agent that monitors the termination of this statement and in-

forms the associated process object. The termination of the “forked” statement is signaled by

and the process that monitors its termination uses the event to inform the process ob-

ject with idx that the execution of its associated statement has terminated.

Done done.0=

[[ X ]] getX x( ) . res x=

[[ self ]] getSelf x( ) . res x=

[[ n ]] res n int,( )=

[[ true ]] res 1 bool,( )= [[ false ]] res 0 bool,( )=

[[ nil ]] res 0 nil,( )=

[[ new C E1 ... En, ,( ) ]] [[ E1 ]] Into x1( ) ... [[ En ]] Into xn( )=

newRequestC x1 ... xn, ,( ) .newIdC x( ) . res x

[[ E. m E1 ... En, ,( ) ]] [[ E ]] Into t( ) [[ E1 ]] Into x1( ) ... [[ En ]] Into xn( )=

requestId k( ) . requestt m, k x1 ... xn, ,( ),( ) . replyk x( ) . res x

[[ E1=E2 ]] [[ E1 ]] Into x1( ) [[ E2 ]] Into x2( ) Comp x1 x2,( )=

Comp i1 c1,( ) i2 c2,( ),( ) =

if c1=c2then ifi1= i2thenres 1 bool,( ) + if i1 i2thenres 0 bool,( ) +≠

if c1 c2thenres 0 bool,( )≠

[[ fork S ]] newRequestproc.newidproc x( ) . res x. [[ S ]] | done. termx( ) \ done=

done termx

Page 113: Language Design Rationale and Semantic Framework for

Defining SCOOL, a Simple Concurrent Object-Oriented Language98

Semantics of Statements

Apart from “E.”, the return statement and the fact that statements are mapped to parameterized

agents, statements and their semantics are the same as those defined in[58] for the languageM0.

“E. ” provides a way to turn expressions into statements by discarding the result yielded by the

expression and by generating the event as required by statements representing agents. It is

useful when a method is invoked for its side effects rather than for its return value. Its semantics,

given below, is straightforward and merits no further discussion.

The return statement deserves some more explanation. Actually it is because of this state-

ment that we have to map statements to parameterized agents. In order to reply to the right caller

the agent representing the return statement has to be parameterized by a value to be used as the

subscript of the reply label. This value is made available in the agent representing method dec-

laration and is passed down to the return statement of a method activation by syntactically en-

closing statements. In fact agents representing the semantics of statements other than the return

statement have no use for this parameter which is either ignored or passed on to the agents cor-

responding to component statements if there are any. The return statement also differs from oth-

er statements in that it does not pass control to the next statement throughdone.Thus, the exe-

cution of a method stops when it encounters a return statement. Instead it generates a

event, directed to the method scheduler, to indicate that the execution of the method has termi-

nated. In case there is no return statement in the method the terminate event is generated by the

MethodBody agent defined in section 1.2.

where

done

terminate

[[ X:= E ]] k( ) [[ E ]] Into x( ) setXx.done( )=

[[ E. ]] k( ) [[ E ]] Into x( ) Done=

[[ { S} ]] k( ) [[ S ]] k( )=

[[ if E then S1 else S2 ]] k( ) =

[[ E ]] Into x( ) if x= 1 bool,( ) then [[ S1 ]] k( ) else [[ S2]] k( )( )

[[ while E do S ]] k( ) W k( )=

W k( ) fix( X= [[ E ]] Into x( ) if x= 1 bool,( ) then [[ S ]] Before XelseDone( )=

[[ S1; S2 ]] k( ) [[ S1]] k( ) Before[[ S2]] k( )=

[[ skip ]] k( ) Done=

[[ return E]] k( ) [[ E ]] Into x( ) replykx. terminate( )=

Page 114: Language Design Rationale and Semantic Framework for

Chapter 5 99

5.2.2.2 Predefined Object Classes

The structure of the process and semaphore predefined classes is the same as the one for user

defined classes so that theClass agent defined in section 1.1 is used for their definition. The only

difference from program-defined classes is that the agents that represent the behavior of instanc-

es are directly encoded in CCS. A quite different approach is illustrated by the agents represent-

ing the predefined Boolean and integer classes.

Process Objects

The purpose of process objects is to delay the invokers of theirwait operation until the thread to

which they are associated terminates. Termination of the thread is signaled to process objects by

a termid event whereid is the object’s identifier, after which the object accepts wait requests,

thus allowing its callers to proceed.

Semaphores

The agentSemaClass, defined below, represents a predefined semaphore class used to create

semaphore instances which are modelled as instances of the SemBehavior agent with the param-

eters bound to the corresponding object identifier. For simplicity we have ignored issues con-

cerning the order in which suspended callers are woken up.

where

,

for and

Booleans

To represent integers and Booleans we take a slightly different approach from the one used

above for semaphores. Here the agents corresponding to the predefined classes directly provide

the behavior of their instances.

ProcBeh id( ) termid. fix X = requestid wait, k ( ),( ) . replyk.X( )=

ProcClass Class process ProcBeh,( )=

SemaClass Class sema SemBehavior,( )=

SemBehavior id p,( ) Sem1 id( )=

Semn id( ) requestid v, k( ) . replyk.Semn 1+ id( ) +=

requestid p, k( ) . replyk.Semn 1− id( )

n 1≥

Sem0 id( ) requestid v, k( ) . replyk.Sem1 id( )=

Page 115: Language Design Rationale and Semantic Framework for

Defining SCOOL, a Simple Concurrent Object-Oriented Language100

The predefined class for Booleans is given below by the agentBoolClass.This agent is de-

fined as the parallel composition of two agents:InstBeh andClassBeh. TheInstBeh agent real-

izes the behavior of the instances of the class which are identified by(0,bool) and(1,bool) for

the objects corresponding to the truth values true and false respectively. For encoding the oper-

ations on Booleans we have made the assumption that Boolean values and the usual Boolean op-

erations are subsumed by the process calculus and we use the symbols 0 and 1 to denote the val-

ues true and false respectively. This assumption, which was not strictly necessary, as we could

have encoded these operations by operations on integers, was made for convenience and in-

creased readability. Also, note that the execution of operations on different Booleans takes place

concurrently as the “product” symbol is used in the definition ofInstBeh to denote parallel com-

position.

Apart from providing the operations of Boolean instances the agentBoolClassalso sup-

ports the behavior of agents representing classes, that is the protocol for the creation of the

class’s instances. This behavior, which is provided by the agentClassBeh, is supported so that

all agents representing classes exhibit uniform behavior. In fact, the object identifier value re-

turned by the Boolean class at the port is the same as the value received along there-

questNewbool port. This value is generated by the agent corresponding to the semantics of the

expressiontrue used, for example, as an argument in the expressionnew Boolean(true) that may

be used for explicitly creating a new instance of an object corresponding to the Boolean value

true. Also, note thatClassBeh handles requests for the creation of instances serially so that no

interference may occur among concurrent requests.

Integers

The predefined class of integers,IntClassis defined below in a way analogous to Booleans. In

order to shorten the presentation just some of the operations typically provided for integers in

programming languages are shown.

newidbool

BoolClass ClassBeh| InstBeh=

ClassBeh= fix( X = requestNewbool n( ) .newidbooln.X )

InstBeh = [ requestn bool,( ) not, r( ) . replyr not n bool,( ) . InstBeh|n 0 1,{ }∈∏

requestn bool,( ) and, r k bool,( ),( ) . replyr k and n bool,( ) . InstBeh]

IntClass IntClassBeh| IntInstBeh=

IntClassBeh requestNewint n( ) .newint n( ) . IntClassBeh=

Page 116: Language Design Rationale and Semantic Framework for

Chapter 5 101

5.3 Accommodating Other Object Models

In this section we define a different version of SCOOL inspired by the language POOL-T[5] and

give its semantics. The facility with which this significantly different version of SCOOL is ac-

commodated provides some evidence concerning the suitability of the proposed framework for

a wide range of concurrent object-based languages.

In this version of SCOOL objects are single threaded active entities that explicitly accept

requests to execute their methods. Method invocation takes place by remote procedure calls. The

caller is suspended until the receiver answers the request and sends back a reply.

A statement, called the object’s body, is associated with each object and starts executing

when the object is created. Ananswer statement may be used in the object’s body to accept re-

quests for executing a method in a specified set. If there are no pending requests for any of the

specified methods the execution of the object’s body is suspended until such a request is made.

After the execution of a method the execution of the object’s body proceeds with the next state-

ment.

It is also possible that a class does not define an object body. In this case a default body is

assumed which repeatedly answers requests for any of the object’s methods.

We also introduce areply statement which is like return in that it sends a reply to the caller

but, unlike return, passes control to the next statement. This statement is used to achieve an ef-

fect similar to POOL-T’s post actions.

5.3.1 Modifying the Syntax

The syntax of this version of SCOOL differs from the one in section 1.2.1 as follows.

Declarations

Class declaration is modified as follows to include the object’s body.

ClassDecl ::= class C { VarDecl MethodDecl1...MethodDecln BodyDecl}

class C { VarDecl MethodDecl1...MethodDecln }

requestn int,( ) minus, r k int,( ),( ) . replyr n k− int,( ) . IntInstBeh |

if n k≠( ) then replyr 1 bool,( ) . IntInstBeh)

( if n=k( ) then replyr 1 bool,( ) . IntInstBeh+requestn int,( ) equal, r k int,( ),( ) .

IntInstBeh= requestn int plus, , r k int, ,( ) . replyr n k+ int,( ) . IntInstBeh |n ℵ∈∏

Page 117: Language Design Rationale and Semantic Framework for

Class Inheritance102

BodyDecl ::= body S

Statements

We extend the definition of statements to include theanswer andreply statements whose syntax

is defined as:

answer (M1,..,Mn) where M1,..,Mn are method names.

reply E

Expressions

We exclude thefork expression since in this version of SCOOL objects are single threaded.

5.3.2 Semantics

Class Declaration

In order to take into account the object’s body we modify the definition of the agentClassBe-

haviorc given in section 1.2.2 as follows.

where

if S is the body declaration for the class C and

if no body declaration is given in the declaration of C.

Method Scheduling

The scheduling of method execution is now done directly by the body so the scheduler in the

definition ofObject is 0.

Semantics of Statements

5.4 Class Inheritance

In this section we discuss how to extend the basic framework of section 1.1 to support class in-

heritance.

ClassBehaviorc id p,( ) Object id meth c( ) [[ VarDecl]] | MethDecl|Body, ,( )=

Body [[ S ]] Before 0=

Body [[ while true answer m1 ... mn, ,( ) ]]=

[[ answer m1 ... mn, ,( ) ]] activatem. terminate.Donem m 1 ... mn,{ , }∈

∑=

[[ reply E]] k( ) [[ E]] Into x( ) replykx.Done( )=

Page 118: Language Design Rationale and Semantic Framework for

Chapter 5 103

First, we include a new agent component, calledSuper, in the assembly of agents that we

used for constructing an object. The purpose of this agen, as we will see shortly, is to allow meth-

ods defined in a class to invoke methods defined in a superclass despite the fact that they have

been overridden in the class.

Next, we modify the definition of agents representing the behavior of program-defined ob-

ject classes to be parameterized by an agent parameter rather than by a value representing an ob-

ject identifier. The resulting structure of agents is illustrated in figure 5.2(a). It is obtained from

figure 5.1 by the addition of SUPER and the introduction of a place holder for an agent in place

of the agent components of figure 5.1.

Figure 5.2

Method Agents

SUPER

Instance Variables

Method Agents

SUPER

Instance Variables

SELF

Request Handler

Method Scheduler

Method Agents

SUPER

Instance Variables

Class definition

Instantiation

Subclass creation

SUPER

without inheritance(a)

(b)

(c)

Page 119: Language Design Rationale and Semantic Framework for

Class Inheritance104

The hole in figure 5.2 can be filled in either by an agent equal to the composition of the

components that were removed from figure 5.1 as illustrated by figure 5.2.(b) or by another

agent with a hole as in figure 5.2(c). The first way to “fill the hole” is used to produce the be-

havior of instances. The second represents class inheritance where two classes are composed to

yield a new class.

5.4.1 Extending SCOOL to Support Inheritance

In order to include inheritance in SCOOL we modify the class declarations as follows:

ClassDecl ::= class C BasicDecl

class C superclass C′ BasicDecl

BasicDecl ::= { VarDecl MethodDecl1...MethodDecln}

A class declaration may optionally specify, by using the keywordsuperclass as indicated above,

that the newly defined class C inherits an already defined class C′.

The semantics of inheritance used for this version of SCOOL is inspired by Smalltalk-80.

A subclass may define methods with the same names as that of its superclass, in which case the

subclass method definition overrides the inherited one. The pseudo variablesuper may be used

by an object to invoke a method of the superclass despite the fact that it has been overridden by

the subclass.

Instance variables defined in a class are accessible in methods of its subclasses and it is not

allowed to redefine them in a subclass.

The pseudo variableself may be used by the object to invoke one of its methods. Invoca-

tions through self will always cause the execution of the most specialized version of the invoked

method.

Method overriding and the super and self features are further discussed in section 1.4.3.

5.4.2 Agent Definitions for Modelling Class Inheritance

The agentObjectBehaviorc, defined below, represents the behavior of C’s instances, and is pa-

rameterized by their object identifiers.

where ms(c) is the set of method names of the class, including the method names of all methods

applicable to the class’s instances, i.e. the new methods defined byc and all the inherited meth-

ods.

ObjectBehaviorc id( ) Object id ms c( ) ClassBehaviorc, ,( )=

Page 120: Language Design Rationale and Semantic Framework for

Chapter 5 105

ObjectBehaviorc is defined in terms of the agentsClassBehaviorc andObject. The former

is an agent with an agent parameter that represents the class C. It has the structure of the agents

with a hole shown in figure 5.2(c) and (a) depending on whether or not inheritance is used in C’s

declaration.

The agentObject fills in the hole of its agent parameter as illustrated in figure 5.2(b), with

the object agent components defined in section 1.1, yielding an agent representing the behavior

of instances of the class. It also restricts the scope of events used for communication between

object components. The way that restriction is used allows us to capture method overriding as it

will be explained in section 1.4.3

whereSch is some method scheduler agent andCl corresponds to the ClassBehaviorc agent for

some class C.

ClassBehaviorc for a class C is defined as follows:

1. if C is defined without making use of inherit-

ance.

2.

where bm(c)

is the set of method names defined inBasic Declc, if an already defined class C' is spec-

ified as C’s superclass.

The restriction ofsuper events in the second case above is necessary to ensure that interaction

will take place with the “right”Super agent. In the case where inheritance was used in the defi-

nition of C' the definition ofClassBehavior for C' also includes aSuper agent.

BasicBehaviorc is obtained from theBasicDecl part of a class C as:

if BasicDeclc = { VarDecl MethodDecl1 ... MethodDecln }, is theBasicDecl part of class’s

C’s declaration, the variables V1,..,Vn are declared inVarDecl.

TheSuper agent operates as an event transducer generating a for eachsuperm event

it consumes, withm in the set of the object’s methods.

Object id m Cl, ,( ) Cl RH id m,( )( ) |Sch m( ) |Self id( )( )=

\ L Sch m( )( ) \ L Self id( )( )

ClassBehaviorc X( ) BasicBehaviorc X( )=

ClassBehaviorc X( ) =

ClassBehaviorc' BasicBehaviorc X( ) | Super bm c( )( )( ) \ superm m bm c( )∈⟨ | ⟩( )

BasicBehaviorc X( ) =

X | [[ VarDecl ]] | [[ MethDecl1]] | ... | [[ MethDecln]]( )

\ ACCV1... \ACCVk

\ callm m bm(c)∈⟨ | ⟩

callm

Page 121: Language Design Rationale and Semantic Framework for

Class Inheritance106

Semantics of Class Declarations

Finally the semantic mapping for class declarations is given as:

Where the agentClassis that defined in section 1.1, and the use of inheritance in the definition

of the class C is taken into account as discussed above in the definition ofClassBehaviorc which

is in turn used to defineObjectBehaviorc.

5.4.3 Overriding Superclass Methods, Self and Super

Overriding of methods is accomplished by the interplay of the restriction of the access sort for

method agents in the definition ofBasicBehaviorc and the operation of the request handler agent.

When a class is instantiated the request handler agent is instantiated within the scope ofBa-

sicBehaviorc whereC is the most specialized class in a chainC1,..,Cn of classes. Because of the

restriction of the access sort of method agents in the definition ofBasicBehaviorc the callm

events generated by the request handler for executing methodm will only be visible to the meth-

od agent form of the most specialized class that definesm. This is illustrated in figure 1.3.

Super meth( ) fix X = superm k a,( ) .callm k a,( ) .Xm meth∈∑( )=

[[ class C BasicDecl]] Class C ObjectBehaviorc,( )=

[[ class C superclass C' BasicDecl]] Class C ObjectBehaviorc,( )=

Figure 5.3

superm1

callm1

callm1SUPER

M1

M1

M2

requestself,m1

\callm1

RH

\callm1\callm2

C1

C2

callm2

Page 122: Language Design Rationale and Semantic Framework for

Chapter 5 107

In some languages, such as Smalltalk-80[34], the pseudo-variablesuper in an expression

like super m1: x, indicates that the search for a method matching the method selector m should

start at the object’s superclass method dictionary. We capture the semantics of super as follows:

• The semantics for an expression involving super is given as:

This way the event will be able to get out of the restriction of the access sorts for methods

of the class. In the enclosing scope this event will be intercepted by theSuper agent and

transduced to a event which is released outside of the class scope of restriction. Thus,

the “search” for a matching method starts at the superclass level.

• A method invocation through the pseudo-variable self appearing in any of the methods of in-

herited classes should cause the invocation of the most specialized version of that meth-

od.This is achieved by using the agent Self to retrieve the object’s id and then using this id for

the call. As self is bound in the most restricted scope it will necessarily cause the invocation

of the most specialized method.

Figure 5.3 illustrates the above for a class C1 which inherits a class C2, having methodsm1

andm2, and which redefines methodm1.

5.5 Considering Other Process Calculi

For developing the framework we have considered two alternative calculi. Although these are

derived from CCS they incorporate features that substantially enhance its expressive power in

ways that are important for modelling some object-oriented concepts. In this section we will dis-

cuss the issues related to the use of these calculi as alternatives for the development of the se-

mantic framework as well as for modeling other object-oriented programming language fea-

tures.

The first of these is theCalculus of Higher Order Communicating Systems, CHOCS, [79]

which extends CCS by allowing processes to be sent and received as values. The second is the

π-calculus [59] where ports or labels may be communicated as values so that systems with dy-

namic communication links between their components may be modelled.

The ability to express systems with dynamic communication topology is essential for mod-

elling object-based systems where objects are created dynamically and object identifiers may be

transmitted in messages. Although we have considered using theπ-calculus for the semantic

[[ super .m E1 ... En, ,( ) ]] [[ E1]] Into x1( ) ... [[ En ]] Into xn( )=

superm k x1 ... xn, ,( ),( ) . replyk x( ) . res x

callmv

Page 123: Language Design Rationale and Semantic Framework for

Considering Other Process Calculi108

framework we finally preferred using CCS. The main reason which is further discussed below

was that the semantic description of some language features was not as direct as one would ex-

pect.

The higher order approach of CHOCS could also be used to model systems with dynamic

communication topology since, as suggested in [79], it is equivalent in expressive power to

ECCS[31], the basis of theπ-calculus. However, in order to go from ECCS to CHOCS a trans-

lation using a kind of continuation semantics is needed. We did not consider taking this approach

for modelling dynamic interconnection since it appears to be less direct for modelling COOPLs

than the approach we used in 1.1.

Apart from modelling systems with dynamic communication topology, the higher order ap-

proach would be useful for modelling features found in some object-based systems that we did

not want to consider in the present framework. These include systems where classes are first

class objects as well as systems based onprototypes anddelegation[47].

For instance, with CHOCS, an object class may be modelled as an agent that stores the de-

scription of the agents corresponding to the class’s methods. Objects of the class receive the de-

scription of the method agents and execute them within a scope that restricts access to the ob-

ject’s instance variables. In this scope references to instance variables in the method agents are

dynamically bound to the instance variables of the instance that executes them. Dynamic chang-

es to classes and to the class inheritance hierarchy can be modelled by changing the description

of method agents held by the agent representing the class or by changing in instances the value

used to identify the agent acting as its class.

5.5.1 Modelling COOPL Features in theπ-Calculus

The ability of theπ-calculus to express the dynamic creation of ports and their communication

among agents is very attractive for modelling object-oriented languages. These features have

been used by Walker to model the semantics of some simple languages[85] in theπ-calculus.

We will first present how theπ-calculus may be used to model COOPLs in a way, basically the

one presented in [85], that takes advantage of the dynamic creation and communication of ports.

Next, we discuss some shortcomings of theπ-calculus and of the approach followed in [85] for

expressing some object-oriented features. Although the main ideas for modelling COOPL fea-

tures in theπ-calculus that we present below come from [85] we take a simpler approach for the

invocation of object operations. This is possible by taking a different approach, discussed at

length below, for modelling primitive objects, than the one followed in [85] that simplifies the

semantics of expressions.

Page 124: Language Design Rationale and Semantic Framework for

Chapter 5 109

5.5.2 Usingπ-Calculus Ports to Represent Object Identifiers

Object identifiers are modelled by theπ-calculus ports that are used for interacting with the

agents representing the corresponding objects. These ports may be stored in variables and used

to communicate with the corresponding objects.

Variables can be modelled in a way similar to the one described in 1.1.3. The only differ-

ence is that now the values stored are ports used to represent object identifiers. The semantics of

the invocation of an object’s operation is to retrieve the port by communication with the variable

agent and then use the received port to communicate with the object.

A class C may be modelled as an agent,Class, that accepts requests for the creation of a

new instance at a portc, wherec is a constant name. For each request it creates a new port:id

which is communicated throughc to the caller. The new port is used for representing the object

identifier of the new instance and is bound to the parameter of an agent, hereObject, that is cre-

ated to represent the new instance.

The following protocol which avoids interference between concurrent requests is used to

model operation invocation. For each request received along the port representing its object

identifier the corresponding agent receives a “private” port that is used for receiving the infor-

mation associated to a request such as a name identifying the requested operation, the opera-

tion’s arguments and sending back the reply.

The agentObject defined below illustrates this approach. First, aprivate port associated

with a particular request is received along the portid. Next, a name identifying the requested op-

eration is received from the private port. According to this name the agent behaves as one of the

agentsMethod1,...,Methodn. These agents are parameterized by the request port which they use

to receive the operation’s arguments and return the result.

The agentCall(id,m,a,result) given below illustrates the sequence of actions that are exe-

cuted at the caller for invoking the operation identified bym of the object associated toid with

a single argument: a and receiving a port identifying the result which is sent along the portresult.

Class c( ) c id( ) . Object id( ) | Class c( )( )=

Object id( ) id r( ) . HandleRequest r( ) |Object id( )( )=

HandleRequest r( ) r : m1 Method1 r( ) ,…,mn Methodn r( )⇒ ⇒[ ]=

Call id m a result, , ,( ) id r( ) . r m. r a. r v( ) . result v=

Page 125: Language Design Rationale and Semantic Framework for

Considering Other Process Calculi110

5.5.3 Comparing Object Identifiers

An issue that is not addressed by the languages modelled in [85] is the possibility to compare the

identity of two objects. In most object-oriented languages an expression like x = y wherex and y

are program variables may be used to compare the equality of the object identifiers stored in

these variables.

The only support offered by theπ-calculus [59] for the comparison of labels is provided

by the “match” operator defined as follows. The agent behaves asP if the

namesx andy are identical otherwise it behaves as 0, the inactive agent. If object identifiers are

modelled asπ-calculus ports, the match operator is not sufficient for describing the semantics of

an expression likex=y, since no action is possible if the compared labels are not identical.

In order to be able to use ports to represent object identifiers theπ-calculus should be ex-

tended with an operator that would better supports the comparison of two names. For instance a

“non-match” or an “if-then-else” operator defined in a way analogous to the match operator.

It would also be possible to use a less direct way for representing object identifiers. For in-

stance, object identifiers could be modelled as pairs of ports consisting of the port used to com-

municate with the agent representing the object and the port of an agent representing an integer

value. The comparison of object identifiers would take place by comparing the associated inte-

ger values which could be encoded in the calculus in the way presented in [85]. Such an ap-

proach however does not take advantage of the features of the calculus that made it in the first

place attractive for modelling object-oriented systems.

5.5.4 Primitive Objects and the Semantics of Expressions

Practically every object-oriented language supports a number of primitive object classes such as

integers and Booleans that are used as the starting point for defining other application specific

classes. With the CCS based approach we followed in 1.2.2 we represented primitive objects and

their classes as agents that observe exactly the same protocol as the agents representing the se-

mantics of program defined classes. With this approach the semantics of expressions, except the

ones that specifically concern primitive objects such as expressions consisting of integer or

Boolean constants, was defined uniformly independently of whether or not they involve primi-

tive objects.

A different approach was followed in [85] for modelling primitive objects using theπ-cal-

culus. With this approach objects of primitive classes such as integer and Boolean values are en-

coded as agents which do not observe the same protocol as the agents representing instances of

x=y[ ] x= y[ ] P

Page 126: Language Design Rationale and Semantic Framework for

Chapter 5 111

program defined classes. The semantics of expressions takes into account the type of the objects

involved and in the case of primitive objects it depends on the structure of the agents that repre-

sent the objects of a particular primitive type.

With respect to the approach that we followed in 1.2.2 the above approach has the disad-

vantage that the semantics of expressions is not defined uniformly independently of the type of

the involved objects. Several cases have to be considered, one for each of the primitive types that

are supported by a particular language. We have considered two alternative approaches for mod-

elling primitive objects in theπ-calculus that overcome the shortcomings of the above approach.

The first approach is to reserve a fixed set of constant names to represent the object identi-

fiers of primitive objects and make use of these names in the encoding of the agents representing

the objects of the type. For example, the fixed constant portstrue andfalse and the agentsTrue

andFalse defined below illustrate this approach for the type Boolean.

The agentTrueencodes the behavior of the object corresponding to the Boolean value true.

It accepts requests at the fixed porttrue over which it communicates the name of a new private

port that is used for getting more information about and for replying to each request. The agent

TrueMethods which is parameterized by the port that is used for an individual request encodes

the operationsnot, or andand for this object.Not has no argument and returns as a result the

constant portfalse that corresponds to the agent that represents the object corresponding to the

Boolean value false.Or inputs from the request port a port corresponding to its argument. It ig-

nores the argument’s value and always replies by sending the port true that corresponds to the

object identifier of the object representing the Boolean value “true.”And inputs the port associ-

ated to its argument which is eithertrue or false and replies by sending back this same port. The

behavior of the agentFalse is analogous to that ofTrue. Integers and other primitive objects may

be represented in a similar way.

Note that only a finite number of integer objects may be represented by following this ap-

proach. This, however, is not a severe shortcoming for the description of the semantics of

COOPLs since we could assume an arbitrary but bounded number of integer objects in the en-

vironment.

True true r( ) . r op( ) . TrueMethods r( ) | True( )=

TrueMethods r( ) r : [ not r false or, r x( ) . r true and, r x( ) . r x ]⇒ ⇒ ⇒=

False false r( ) . r op( ) . FalseMethods r( ) | False( )=

FalseMethods r( ) r : [ not r true or, r x( ) . r x and, r x( ) . r false]⇒ ⇒ ⇒=

Page 127: Language Design Rationale and Semantic Framework for

Concluding Remarks112

The second approach for representing primitive objects such as Booleans and integers is to

maintain the representation of integer and Boolean values as given in [85] but provide an object

interface to these representations so that the semantics of expressions may be defined in a uni-

form way for all objects. This may be accomplished by encoding objects of primitive types, say

integers, as follows. The agent representing the integer object stores the port of an agent that en-

codes an integer value in the way presented in [85]. Integer operations are realized by operating

on this representation, creating and returning a new integer object associated with the resulting

representation.

With this approach it is not necessary to fix a finite number of ports to be used as the object

identifiers of agents that represent integers. Each time an integer is returned as the result of an

operation on integers a new port could be created for the integer object associated with the inte-

ger value corresponding to the result of the operation. However, if a new port is used each time

that an integer object is returned as the result of an operation on integers different integer objects

would be used for representing the same integer value. The result of this would be that the se-

mantics of = based on the ports used for representing object identifiers would not coincide with

the equality of the integer values. A way to ensure that exactly one integer object is used for each

integer value is to have an agent in the environment that, based on the integer value, creates and

returns the port of an integer object. This agent would remember the ports used by integer ob-

jects associated with each integer value so that at most one integer object would be created for

an integer value. The main disadvantage of this approach is that it is heavily operational.

5.6 Concluding Remarks

We have presented a framework for describing the semantics of concurrent object-oriented lan-

guages and features. This framework captures the essential concepts found in COOPLs such as

objects and object identifiers, concurrent execution, classes and class inheritance. It provides a

high level description of the semantics of language features that makes it possible to compare

the different language design approaches and investigate in a formal setting the interaction of

features such as inheritance and synchronization.

The framework captures the common structure of object-oriented features by a set of defi-

nitions of agents with agent parameters. These parameterized agents may be viewed as the op-

erators of a derived calculus that supports in a more direct way object-oriented features and

makes it easier to describe and understand the semantics of COOPLs. The different language de-

sign approaches may be represented either by varying the agent parameters or by modifying the

definition of certain parameterized agents.

Page 128: Language Design Rationale and Semantic Framework for

Chapter 5 113

Although CCS does not directly support the representation of systems with dynamic inter-

connection structure it is possible to encode object-oriented languages by assuming a static in-

terconnection network where any object may interact with any other object and where object

identifiers act as switches for communicating with a particular object. This could be done in a

more elegant and direct way by using theπ-calculus which directly supports the dynamic cre-

ation and establishment of communication links. However, in order to take advantage of these

features it is necessary to extend the calculus by an operator that better supports the comparison

of ports. Also, some more work is needed for representing primitive object types.

An important consequence of using a process calculus such as CCS as the target for the se-

mantics is that the underlying calculus may be used to formally specify and verify properties of

languages and systems.

The meaning of individual classes is given by a term of the calculus and it is possible to

use the calculus to examine whether this term is, in some sense, equivalent to an agent directly

expressed in CCS and which corresponds to the abstract specification of an object’s behavior.

Moreover, equivalence classes of CCS agents may be used as a specification of object behavior

that abstracts to some extent from a particular implementation of this behavior. We further dis-

cuss this issue in chapter 6.

The properties of the derived operators that we have defined, as agents with agent parame-

ters, for representing language features can be investigated by using the underlying process cal-

culus. The analysis of these operators and their interaction can be used to infer useful informa-

tion about the language design and the combination of the features of a language.

Page 129: Language Design Rationale and Semantic Framework for
Page 130: Language Design Rationale and Semantic Framework for

CHAPTER 6

Conclusion

The development of concurrent object-oriented languages that integrate object-oriented and

concurrent programming features is essential for taking advantage of object-oriented techniques

and their software reuse potential for constructing concurrent software. However, issues of con-

currency are not orthogonal to object-oriented concepts. Consequently, the benefits of the ob-

ject-oriented features do not carry over to languages providing arbitrary combinations of object-

oriented and concurrency features because of the interference of the object-oriented and concur-

rency features.

Another difficulty for taking advantage of the reuse potential of object-oriented techniques

for constructing concurrent software by reusing objects across applications and by enhancing ex-

isting object classes in an upward compatible way that does not break existing programs, it is

required to have a precise understanding of the behavior of objects. However, understanding the

behavior of objects and whether or not object behaviors are compatible, can be rather subtle in

the case of concurrent objects. We have addressed these problems by:

• A language design framework for understanding the interaction of concurrency and ob-

ject-oriented features in COOPLs and for comparing the language design choices with

respect to the integration of the concurrency and object oriented features. Using this

framework we have identified a number of combinations of language design choices that

satisfactorily integrate concurrency and object-oriented programming.

• A framework for the description of the semantics of COOPLs. This framework provides

a formal setting for specifying the semantics of COOPL features, examining their inter-

action and, most importantly, it provides a rigorous notion of behavior for concurrent ob-

jects.

Page 131: Language Design Rationale and Semantic Framework for

116 Summary

6.1 Summary

6.1.1 Language Design Framework

6.1.1.1 Understanding the Language Choices

To understand the interaction of the concurrency and object features and what are the essentially

different approaches for the design of COOPLs we have constructed a design space that captures

the possible choices concerning three aspects of the language design.

• Object models: How are objects considered with respect to concurrent execution.

• Object threads: How many threads do objects have and how they are scheduled and created.

• Object interaction: What constructs are provided for objects to accept requests, issue requests

and receive replies.

Object Models

• The Orthogonal Approach: Concurrent execution is independent of objects which are consid-

ered as passive abstract data types shared by concurrent threads.

• The Homogeneous Approach: Objects are considered as active server entities that accept re-

quests from other objects.

• The Heterogeneous Approach: Both passive and active objects are supported. The languages

ensure that only active objects are used in places where the object’s operations may be in-

voked concurrently.

Object Threads

With respect to the number and scheduling of concurrent threads within an object, a language

may support one of the three kind of objects:

• Sequential: Objects have a single thread of control.

• Quasi-Concurrent: There can be more than one thread of control but only one is active at a

time. Thread switching is explicit.

• Concurrent: There are several, conceptually, parallel threads within the object.

There are two, non exclusive, ways for the creation of threads which are:

• By message reception: In this cases the creation of the thread is triggered by the arrival of a

message. There two disjoint subcategories according to whether the object may constrain the

creation of threads or not, that we have namedunconstrained andcontrolled thread creation.

Page 132: Language Design Rationale and Semantic Framework for

Chapter 6 117

• Explicit creation: In this case a new thread may be created by the execution of a special con-

struct by an already active thread.

Object Interaction

We have examined the features provided for object interaction by considering separately the as-

pects related to issuing requests by an object playing the role of a client and accepting requests

by an object acting as a server.

We have divided the approaches for issuing requests into the following depending on

whether or not the mechanism support the notion of reply and the mechanisms for receiving the

reply to a request:

• One-way messages: Replies are not supported, they have to be sent as independent messages.

• Request/Reply: Support is provided for replies. We can further subdivide this category into

Remote procedure call andproxy based approaches. With the latter, the reply can be received

explicitly at a time that is determined by the caller.

Depending on whether or not some mechanism is supported for specifying which requests

may be accepted in the current state of an object, we distinguish betweenunconditional andcon-

ditional acceptance of requests. The following approaches may be used for conditional accep-

tance of requests:

• Explicit Acceptance: A statement is executed by the object to accept requests for calling some

of its methods.

• Activation Conditions: Each method is associated with a predicate that depends on the ob-

ject’s state and, possibly, on the method arguments. A call for a method is accepted only when

its associated condition is true. Activation conditions may berepresentation specific or ab-

stract. The former are expressed directly on the instance variables that are used in the imple-

mentation of the class. The latter are expressed on some abstraction of the object’s state.

• Reflective Computation: The arrival of a message activates the objects metaobject. The meta

object examines the state of its associated object and the contents of the message and decides

whether to call the requested method.

6.1.1.2 Language Design Criteria

For comparing the language design choices in each aspect of the language design space, we de-

veloped a set of requirements that express the integration of concurrency with object-oriented

concepts. The main idea underlying these requirements is that objects should make minimal as-

Page 133: Language Design Rationale and Semantic Framework for

118 Summary

sumptions about applications that use them and about the behavior of objects with which they

interact. The features supported by COOPLs should make it easy to program such objects.This

main idea is refined in the following points:

1. Mutual Exclusion: The internal state of objects should be automatically protected from

concurrent invocations.

2. Request Scheduling Transparency:An object should be able to delay the servicing of

requests based on its current state and on the nature of the request. This should be accom-

plished in a way that is transparent to the client.

3. Internal Concurrency: The concurrency constructs should allow for the implementation

of objects that service several requests in parallel or that make use of parallelism in their

implementation for increased execution speed in the processing of a single request.Int-

ernal concurrency should be transparent to the object’s clients.

4. Reply Scheduling Transparency:A client should not be forced to wait until the serving

object replies. Request scheduling by the client should not require the cooperation of the

server since this would limit the ability to combine independently developed clients and

servers.

5. Compositionality and Incremental Modification:Existing object classes should be re-

usable within new contexts without modification. Additionally, mechanisms for incre-

mental modification of classes such as class inheritance must be designed with special

consideration given to concurrency to allow existing code to cooperate gracefully with

modifications and extensions.

6.1.2 Evaluating Design Choices and their Combinations

In chapter 4 we have examined the design choices and based on examples that illustrated the de-

sign choices, or combinations of design choices, that failed to address our requirements. We fi-

nally came up with a set of design choice combinations and guidelines for the design of COOPLs

that achieve a satisfactory integration of concurrency and object-oriented programming.

Request and Reply Scheduling

Request and reply scheduling can be supported equally well by sequential objects and multi-

threaded objects provided that these are combined with the appropriate object interaction mech-

anisms.

Page 134: Language Design Rationale and Semantic Framework for

Chapter 6 119

In the case of sequential objects it is necessary to support a communication mechanism that

does not block the object’s single thread for receiving replies. The best solution, found in the

languages that we examined, is to use an approach that integrates one-way messages with rpc.

There is also the alternative to use proxies, provided that it be possible for the object’s thread to

wait on either the arrival of the reply by the proxy or the arrival of further requests. However,

no such mechanism was supported by any of the proxy based approaches that we examined.

In the case of multi-threaded objects, thread creation should be controlled by the object.

Supporting unconstrained creation of concurrent threads is similar to the orthogonal approach

for the language’s object model which violates the mutual exclusion requirement.

To support the request/reply scheduling requirements for quasi-concurrent threads it is nec-

essary to have a mechanism that allows another thread to be scheduled when the active thread

blocks for receiving the reply to a request. This is not necessary in the case of concurrent threads

since there may be other active threads within the object.

If rpc is chosen as the main communication mechanism it is also necessary to either support

explicit creation of threads or use proxies or one-way message passing for allowing to a single

thread to issue concurrent requests. If proxies are used, in the case of concurrent threads it is not

necessary, as in the case of sequential objects, to provide a mechanism for combining the accep-

tance of a request and a reply from a proxy. Separate threads can be used for each of these tasks.

Internal Concurrency

Internal concurrency can be addressed satisfactorily either by supporting concurrent threads or

by implementing an object as a collection of concurrent objects provided that the object interac-

tion constructs satisfactorily address request/reply scheduling. However, concerning the latter,

special care has to be taken so that the collection may present the same interface and be substi-

tutable with a single object implementation.

Both these approaches for internal concurrency are useful for different purposes. Concur-

rent threads make it easy to implement objects that may service several concurrent requests that

do not modify the objects state. Multi-object approaches are interesting when the implementa-

tion of a new object class, with internal concurrency, may be realized by using several concur-

rently executing instances of existing object classes.

6.1.3 Formally Specifying the Semantics of COOPLs and of Active Objects

For a rigorous description of the semantics of COOPL and of the behavior of objects specified

in these languages, we have developed, in chapter 5, a framework for describing the semantics

Page 135: Language Design Rationale and Semantic Framework for

120 Open Problems and Future Research Directions

of concurrent object-oriented languages and features in CCS. The framework captures the essen-

tial concepts found in COOPLs such as objects and object identifiers, concurrent execution,

classes and class inheritance. It provides a high level description of the semantics of language

features that makes it possible to compare the different language design approaches and inves-

tigate in a formal setting the interaction of features such as inheritance and synchronization.

The common aspects of COOPL are captured by defining agents with agent parameters that

can be viewed as the operators of a derived calculus that allows a more direct description of the

semantics of COOPLs. The different language design approaches can be represented either by

varying the agent parameters or by modifying the definition of certain parameterized agents.

An important benefit of our approach for describing the semantics of COOPLs is that it pro-

vides a rigorous definition of the behavior of objects as a CCS agent. This allows the underlying

formal CCS framework to be used for reasoning and verifying behavioral properties of objects,

and provides us with rigorous notions of behavioral equivalence and substitutability of objects

induced by the corresponding notions on CCS agents.

6.2 Open Problems and Future Research Directions

6.2.1 Taking Advantage of Class Inheritance in COOPLs

Our language design requirements stated that the design of the concurrency mechanisms of

COOPLs should be easy to combine with mechanisms such as class inheritance to allow reuse

at a finer grain than whole objects. However, as it was shown in chapter 2 with the synchroniza-

tion mechanisms of Hybrid and as we discussed in chapter 4, class inheritance interferes with

encapsulation and synchronization. The design of synchronization mechanisms that can be suc-

cessfully combined with class inheritance is a research area in its own right. Moreover, the de-

sign of the synchronization mechanisms, apart from making it possible to take advantage of class

inheritance, should, at the same time, address the other requirements that we formulated for the

concurrency features of COOPLs.

The main trend in recent proposals for taking advantage of inheritance and finer grain reuse

have focused on separating the synchronization constructs from the method code. In that way

the code of inherited methods does not have to be modified in case that the synchronization con-

straints of a class that inherits a method, differ, with respect to this method, from the constraints

of the class where the method was originally defined.

With some approaches the synchronization constraints on the acceptance of requests may

have to be completely redefined in the subclass. In other approaches the synchronization con-

Page 136: Language Design Rationale and Semantic Framework for

Chapter 6 121

straints may be inherited and combined with the constraints of other methods in the subclass.

Yet other approaches attempt to specify and reuse independently the “sequential part” of an ob-

ject and the synchronization specification.

The main problems with most of these approaches, as discussed in chapter 4, are:

• The synchronization mechanisms are weak for cases where a method has to be blocked

in mid-stream, allow another method to execute, and resume its execution at some later

time. However, supporting such behavior is essential for flexible reply scheduling.

• Although, the specification of synchronization constraints for a class is kept separate

from the method code they are not independent. The implementation of the methods is

known and the constraints are specified in a way that prevents the concurrent execution

of methods using the same instance variables. Changing the implementation of a parent

class may cause that the synchronization constraints in subclasses have to be modified.

As discussed in [75] having to modify subclasses after changing the definition of a parent

class is contrary to encapsulation.

6.2.2 Object Behavior, Behavioral Equivalence and Substitutability

An advantage of our approach to the semantics of COOPL is that it gives a clear meaning, rep-

resented by a CCS agent, to individual object classes. Thus, one can use the underlying theoret-

ical framework to reason about the semantics of classes and, motivated by substitutability, in-

vestigate notions of behavioral equivalence of object classes that are induced from equivalence

relations on CCS agents and alternatively try to capture formally at the CCS level intuitive ideas

about behavioral equivalence of object classes.

An interesting equivalence relation on object classes is the one induced by the CCS equal-

ity,= [58]. By the fact that the agents corresponding to the semantics of two object classes are

equal we may infer that the object classes and their instances may be safely interchanged in a

system. The behavior of the resulting systems, understood as agents, will be equal. This equiv-

alence relation has the benefit that it captures substitutability and to a certain extent abstracts

from the implementation of classes since actions related to the implementation, modelled as, si-

lent,τ- transitions, are ignored by this equivalence.

A closer examination reveals, however, that this object equivalence does not capture our

intuitions about what constitutes equivalent object behavior. For instance, the desired behavior

may be realized in a way that an object may have to communicate with other objects to which it

got acquainted at its creation or new objects it created to use them in its implementation. Clearly,

Page 137: Language Design Rationale and Semantic Framework for

122 Open Problems and Future Research Directions

different implementations of the object’s behavior may exhibit different object creation and in-

teraction patterns. These actions however are not represented byτ-transitions since they are used

for the interaction of the object with its environment.

As another example, consider two objects that although may service the same requests, one

accepts and processes several “read-only” requests in parallel while the other accepts the same

kind of requests serially. Even if the difference in implementation of these objects is abstracted

by silent actions - if, for example, their methods just read their instance variables - these objects

are not equivalent because of the different possible patterns of request acceptance.

By using the semantic framework presented in chapter 5 we may investigate the properties

of alternative equivalence relations on CCS agents, for example those discussed in section 6.2.3

below, that capture our intuitions about the equivalence of objects and which induce a congru-

ence in the restricted classes of CCS contexts that correspond a particular language. Such equiv-

alence relations may also be used as the basis for comparing language designs. We can investi-

gate whether the features of the language design preserve the desirable equivalences, thus pro-

viding substitutability of equivalent objects, in order to identify problematic design choices.

An important consequence of using a process calculus such as CCS as the target for the se-

mantics is that the underlying calculus may be used to formally specify and verify properties of

languages and systems.

The meaning of individual classes is given by a term of the calculus and it is possible to

use the calculus to examine whether this term is, in some sense, equivalent to an agent directly

expressed in CCS and which corresponds to the abstract specification of an object’s behavior.

Moreover, equivalence classes of CCS agents may be used as a specification of object behavior

that abstracts to some extent from a particular implementation of this behavior.

6.2.3 Types as Behavioral Constraints for Active Objects

A closely related but different issue from behavioral equivalence is a notion of object type that

captures information about the behavior of active objects. Types in context of object-oriented

programming languages[20][80] may be understood as a predicate that is satisfied by the objects

that belong to the type. This view of types may be adapted to concurrent objects by suitable ways

to express as predicates behavioral constraints on the agents that represent the behavior of ob-

jects. Below we consider some ways for expressing predicates that capture behavioral con-

straints for concurrent objects.

Page 138: Language Design Rationale and Semantic Framework for

Chapter 6 123

The most direct approach for expressing a predicate on the behavior of objects is to require

that the agent, corresponding to the meaning of the object expressed in some COOPL, be equiv-

alent to some agent, directly expressed in CCS, that is used to specify the behavior of objects of

a type. A type is the set of objects that satisfy this predicate, that is, the objects whose semantics

correspond to agents that are equivalent to the agent representing the type.

This approach however is a too narrow interpretation of types since it completely specifies

the behavior of objects and it fails to capture polymorphism and subtyping relations between

types. If an object satisfies the predicate of two types these types have to be equivalent. Also,

clearly, an object may not satisfy a type specification that does not include all of its operations.

Alternative approaches based on relations among agents are to consider asymmetric relations

and context dependent equivalences [45] between agents.

The approach of using asymmetric relations, suggested in [67], may be used to express sub-

typing relations between the agents that are used for the type specifications. A subtype should

be able to simulate every action of the supertype but it may also provide additional behavior that

is not provided by the supertype.

A context dependent equivalence relation may be used to express the substitutability of

agents within a certain context. A concrete case of a parameterized equivalence was presented

in [45] where bisimulation equivalence is parameterized by information aboutenvironments. An

environment consumes actions that are produced by an inner process. However the ability of the

environment to consume actions may be limited. Two processes are considered equivalent in an

environment if, in a sense, they are equivalence with respect to the actions consumed by the en-

vironment. Environments may thus be used to consider only the actions related to the set of op-

erations of a type.

Another interesting approach is to use some modal logic [58][36][46] for the partial speci-

fication of the behavior of objects represented as an agent. A type may then be understood as the

set objects whose behavior satisfies the partial specification. This approach also supports a no-

tion of subtyping as implication between modal logic formulas.

The above approaches for defining a notion of types can be used as yardsticks in the develop-

ment of type expression sub-languages for COOPLs that capture more information about the dy-

namic aspects of object behavior than those of actual COOPLs that approximate the notions sub-

stitutability induced by these notions of types.

Page 139: Language Design Rationale and Semantic Framework for
Page 140: Language Design Rationale and Semantic Framework for

References

[1] G.A. Agha,ACTORS: A Model of Concurrent Computation in Distributed Systems, The MIT Press, Cam-

bridge, Massachusetts, 1986.

[2] A.V. Aho, R. Sethi and J.D. Ullman,Compilers Principles, Techniques and Tools, Addison Wesley, 1986.

[3] S.Andler, ‘‘Predicate Path Expressions,’’ inProc. of 6th ACM POPL, SIGPLAN, ACM, 1979.

[4] P. America, ‘‘Inheritance and Subtyping in a Parallel Object-Oriented Language,’’ inProc. ECOOP’87,BI-

GRE, no. 54, pp. 281-289, June 1987.

[5] P. America, “POOL-T: A Parallel Object-Oriented Language,” inObject-Oriented Concurrent Program-

ming, ed. A. Yonezawa, M. Tokoro, pp. 199-220, The MIT Press, Cambridge, Massachusetts, 1987.

[6] P. America, ‘‘A Behavioural Approach to Subtyping in Object-Oriented Programming Languages,’’ inPro-

ceedings of the Workshop on Inheritance Hierarchies in Knowledge representation and programming Lan-

guages, pp. 141-156, Viareggio, Italy, Feb. 1989.

[7] P. America and F. van der Linden, ‘‘A Parallel Object-Oriented Language with Inheritance and Subtyping,’’

Proc. OOPSLA’90, SIGPLAN Notices, vol. 25, no. 10, pp. 161-168, ACM Press, October 1990.

[8] American National Standards Institute, Inc.,The Programming Language Ada Reference Manual, Lecture

Notes in Computer Science 155, Springer-Verlag, 1983.

[9] G.R. Andrews and F.B. Schneider, ‘‘Concepts and Notations for Concurrent Programming,’’ ACM Comput-

ing Surveys, vol. 15, no. 1, pp. 3-43, March 1983.

[10] G.R. Andrews, R.A. Olsson and M. Coffin, “An Overview of the SR Language and Implementation,” TO-

PLAS, vol. 10, no. 1, pp. 51-86, ACM, January 1988.

[11] H.E. Bal, J.G. Steiner and A.S. Tanenbaum, ‘‘Programming Languages for Distributed Computing Sys-

tems,’’ ACM Computing Surveys, vol. 21, no. 3, pp. 261-322, September 1989.

[12] T. Biggerstaff and C. Richter, ‘‘Reusability Framework, Assessment and Directions,’’ IEEE software, vol. 4,

no. 2, pp. 41-49, March ’87.

[13] A. Bjornerstedt and S. Britts, ‘‘AVANCE: An Object Management System,’’Proc. OOPSLA’88, SIGPLAN

Notices, vol. 23, no. 11, pp. 206-221, ACM, san diego, November 1988.

[14] A. Black, N. Hutchinson, E. Jul and H. Levy, “Object Structure in the Emerald System,” Proc. OOPSLA’86,

ACM SIGPLAN Notices, vol. 21, no. 11, pp. 78-86, Nov 1986.

[15] T. Bloom., ‘‘Evaluating Synchronization Mechanisms,’’ inProceedings of the Seventh Symposium on Oper-

ating System Principles, ACM-SIGOPS, December 1979.

[16] Brinch Hansen, P., ‘‘The Programming Language Concurrent Pascal,’’ IEEE Transactions on Software En-

gineering, vol. SE-1, pp. 199-207, June 1975.

[17] J-P. Briot and A. Yonezawa, ‘‘Inheritance and Synchronization in Concurrent OOP,’’Proc.ECOOP’87, Paris,

France, June 1987,BIGRE, no. 54, pp. 35-43, June 1987.

Page 141: Language Design Rationale and Semantic Framework for

126 References

[18] J.P. Briot, “Actalk: A Testbed for Classifying and Designing Actor Languages in the Smalltalk-80 Environ-

ment,” inProc. ECOOP’89, ed. S. Cook, British Computer Society Workshop Series, Cambridge University

Press, 1989.

[19] R.H. Campbell and A.N. Habermann, ‘‘The Specification of Process Synchronization by Path Expressions,’’

LNCS, vol. 16, pp. 89-102, Springer-Verlag, New York, 1974.

[20] L. Cardelli and P. Wegner, ‘‘On Understanding Types, Data Abstraction, and Polymorphism,’’ ACM Com-

puting Surveys, vol. 17, no. 4, pp. 471-523, December 1985.

[21] D. Caromel, “Concurrency and Reusability: From Sequential to Parallel,” JOOP, Sept./Oct. 1990.

[22] R.L. Cook, F.L. Rawson III, J.A. Tunkel and R.L. Williams,”Writing an Operating System/2 Application,”

IBM Systems Journal, vol. 27, no. 2, pp. 134-157, 1988.

[23] Courtois P., Heymans F. and Parnas D., ‘‘Concurrent Control with Readers and Writers,’’ Communications

of the ACM, vol. 14, no. 10, pp. 667-668, Oct. 1971.

[24] W. Cook, ‘‘A Proposal for Making Eiffel Type-Safe,’’ inProc. ECOOP’89, ed. S. Cook, British Computer

Society Workshop Series, Cambridge University Press, 1989.

[25] B.J. Cox,Object Oriented Programming: An Evolutionary Approach, Addison-Wesley, 1986.

[26] S. Danforth and C. Tomlinson, ‘‘Type Theories and Object-Oriented Programming,’’ ACM Computing Sur-

veys, vol. 20, no. 1, pp. 29-72, March 1988.

[27] D. Decouchant, S. Krakowiak, M. Meysembourg, M. Rivelli and Rousset de Pina, ‘‘A Synchronization

Mechanism for Typed Objects in a Distributed System,’’ SIGPLAN Notices, vol. 24, no. 4, ACM, April 1989.

[28] L. P. Deutsch, ‘‘Reusability in the Smalltalk-80 Programming system,’’ inIEEE Tutorial on Software reus-

ability 1987.

[29] L. P. Deutsch, ‘‘Levels of reuse in the Smalltalk-80 programming system,’’ inTutorial: Software reusability,

ed. P. Freeman, IEEE Computer Society Press, 1987.

[30] L.P. Deutsch, ‘‘Design Reuse and Frameworks in the Smalltalk-80 system,’’ inSoftware Reusability, ed. T.J.

Biggerstaff and A.J. Perlis, vol. 2, pp. 57-71, ACM Press, 1989.

[31] U. Engberg and M. Nielsen, ‘‘A Calculus of Communicating Systems with Label Passing,’’ DAIMI PB-208,

University of Aarhus, 1986.

[32] W.M. Gentleman, “Message Passing Between Sequential Processes: the Reply Primitive and the Administra-

tor Concept,” Software-Practice and Experience, vol. 11, pp. 435-466, 1981.

[33] S.J. Gibbs, D.C. Tsichritzis, E. Casais, O.M. Nierstrasz and X. Pintado, ‘‘Class Management for Software

Communities,’’ Communications of the ACM, vol. 33, no. 9, pp. 90-103, Sept 1990.

[34] A. Goldberg and D. Robson,Smalltalk-80: The Language and its Implementation, Addison-Wesley, 1983.

[35] M. Gordon ,The denotational description of programming languages, springer verlag, 1979.

[36] M. Hennessy and R. Milner, ‘‘Algebraic Laws for Nondeterminism and Concurrency,’’ Journal of the ACM,

vol. 32, no. 1, pp. 137-161, Jan 1985.

[37] C.A.R Hoare, ‘‘Proof of correcteness of data representations,’’ Acta Informatica, vol. 1, pp. 271-281, Feb.

1972.

[38] C.A.R. Hoare, “Monitors : An Operating System Structuring Concept,” CACM, vol. 17, no. 10, pp. 549-557,

ACM, October 1974.

[39] C.A.R. Hoare, “Communicating Sequential Processes,” CACM, vol. 21, no. 8, pp. 666-677, Aug 1978.

[40] R. E. Johnson and B. Foote, ‘‘Designing Reusable Classes,’’ JOOP, pp. 22-35, June/July 1988.

[41] D. G. Kafura and K. H. Lee, ‘‘Inheritance in Actor Based Concurrent Object-Oriented Languages,’’ inProc.

ECOOP’89, ed. S. Cook, British Computer Society Workshop Series, Cambridge University Press, 1989.

Page 142: Language Design Rationale and Semantic Framework for

References 127

[42] D. Konstantas, O.M. Nierstrasz and M. Papathomas, ‘‘An Implementation of Hybrid,’’ inActive Object En-

vironments,Centre Universitaire d’Informatique, University of Geneva, ed. D. Tsichritzis, pp. 61-105, 1988.

[43] S. Krakowiak et al.,”Design and Implementation of an Object-Oriented, Strongly Typed Language for Dis-

tributed Applications,” JOOP, September/October 1990, pp. 11-22.

[44] B.W. Lampson and D.D. Redell, ‘‘Experience with Processes and Monitors in Mesa,’’ Communications, vol.

23, no. 2, pp. 105-117, ACM, 1980.

[45] K.G. Larsen, ‘‘A Context Dependent Bisimulation between Processes,’’ Theoretical Computer Science, no.

49, pp. 185-215, 1987.

[46] K.G. Larsen, ‘‘Proof Systems for Hennessy-Milner Logic with Recursion,’’ inProceedings CAAP ’88, ed.

M. Dauchet, M. Nivat, LNCS 299, pp. 215-230, Springer-Verlag, Nancy, March 1988.

[47] H. Lieberman, ‘‘Using Prototypical Objects to Implement Shared Behavior in Object Oriented Systems,’’

ACM SIGPLAN Notices, Proceedings OOPSLA ’86, vol. 21, no. 11, pp. 214-223, Nov 1986.

[48] B. Liskov, A. Snyder, R. Atkinson and C. Schaffert, ‘‘Abstraction Mechanisms in CLU,’’ CACM, vol. 20,

no. 8, pp. 564-576, Aug 1977.

[49] B. Liskov and S. Zilles, ‘‘Programming with Abstract Data Types,’’ Proceedings of the ACM Symposium on

Very High Level Languages, SIGPLAN Notices, vol. 9, no. 4, pp. 50-59, 1974.

[50] B. Liskov, M. Herlihy and L. Gilbert, ‘‘Limitations of Synchronous Communication with Static Process

Structure in Languages for Distributed Computing,’’ inProceedings of the 13th ACM POPL, St. Petersburg,

Florida, 1986.

[51] B. Liskov, ‘‘Distributed Programming in Argus,’’ ACM Communications, vol. 31, no. 3, pp. 300-313, March

1988.

[52] A. Lister, ‘‘The Problem of Nested Monitor Calls,’’ ACM Operating Systems Review, pp. 5-7, Jul. 1977.

[53] P. Maes, ‘‘Computational Reflection,’’ Technical Report 87-2, Artificial Inteligence Laboratory, Vrije Uni-

versity Brussels, 1987.

[54] P. Maes, ‘‘Concepts and Experiments in Computational Reflection,’’ in .Proc. OOPSLA’87, SIGPLAN No-

tices, vol. 22, no. 12, Dec. 1987.

[55] S. Matsuoka, K. Wakita and A. Yonezawa,Analysis of Inheritance Anomaly in Concurrent Object-Oriented

Languages (Extended Abstract), To appear, SIGPLAN Notices, Proceedings of OOPSLA/ECOOP’90 work-

shop on Object-Based Concurrent Systems.

[56] B. Meyer,Object-oriented Software Construction, Prentice Hall, New York, 1988.

[57] B. Meyer, ‘‘Reusability: The Case for Object-Oriented Design,’’ IEEE Software, vol. 4 , no. 2, pp. 50 - 64,

March 1987.

[58] R. Milner,Communication and Concurrency, Prentice Hall International Series in Computer Science, 1989.

[59] R. Milner, J. Parrow and D. Walker, ‘‘A Calculus of Mobile Processes, Part I and II,’’ Report ECS-LFCS-

89-85 and -86, Laboratory for Foundations of Computer Science, Computer Science Department, University

of Edinburgh, 1989.

[60] J.E.B. Moss and W.H. Kohler, “Concurrency Features for the Trellis/Owl Language,” Proceedings of

ECOOP ‘87,BIGRE, no. 54, pp. 223-232, June 1987.

[61] C. Neusius,Synchronizing Actions, LNCS, 512, pp. 118-132, Springer Verlag, July 1991, Proceedings of

ECOOP’91, Geneva, Switzerland.

[62] O. Nierstrasz, ‘‘Active Objects in Hybrid,’’Proc. OOPSLA’87, SIGPLAN Notices, vol. 22, no. 12, pp. 243-

253, Dec. 1987.

[63] O.M. Nierstrasz, ‘‘Triggering Active Objects,’’ inObjects and Things, ed. D.C. Tsichritzis, pp. 43-78, Centre

Universitaire d’Informatique, University of Geneva, March 1987.

Page 143: Language Design Rationale and Semantic Framework for

128 References

[64] O.M. Nierstrasz, “A Survey of Object-Oriented Concepts,” in Object-Oriented Concepts, Databases and Ap-

plications, ed. W. Kim and F. Lochovsky, pp. 3-21, ACM Press, 1989.

[65] O.M. Nierstrasz, ‘‘A Guide to Specifying Concurrent Behavior with Abacus,’’ inObject Management, ed.

D.C. Tsichritzis, pp. 267-293, Centre Universitaire d’Informatique, University of Geneva, July 1990.

[66] O.M. Nierstrasz and M. Papathomas, ‘‘Viewing Objects as Patterns of Communicating Agents.,’’ ACM SIG-

PLAN Notices, vol. 25, no. 10, ACM Press, October 1990.

[67] O.M. Nierstrasz and M. Papathomas, ‘‘Towards a Type Theory for Active Objects,’’ inObject Management,

Centre Universitaire d’Informatique, University of Geneva, ed. D. Tsichritzis, pp. 295-304, 1990, To appear,

SIGPLAN Notices, Proceedings of OOPSLA/ECOOP’90 workshop on Object-Based Concurrent Systems..

[68] M. Papathomas and D. Konstantas, ‘‘Integrating Concurrency and Object-Oriented Programming: An Eval-

uation of Hybrid,’’ inObject Management, Centre Universitaire d’Informatique, University of Geneva, ed.

D. Tsichritzis, pp. 229-244, 1990.

[69] M. Papathomas, ‘‘Concurrency Issues in Object-Oriented Languages,’’ inObject Oriented Development ,

Centre Universitaire d’Informatique, University of Geneva, ed. D. Tsichritzis, pp. 207-245, 1989.

[70] D.L. Parnas, ‘‘A Technique for Software Module Specification with Examples,’’ CACM, vol. 15, no. 5, pp.

330-336, May 1972.

[71] D.L. Parnas, ‘‘On the Criteria to be Used in Decomposing Systems into Modules,’’ CACM, vol. 15, no. 12,

pp. 1053-1058, December 1972.

[72] D.L. Parnas, ‘‘The Non-Problem of Nested Monitor Calls,’’ ACM Operating Systems Review, vol. 12, no. 1,

pp. 12-14, 1978.

[73] G. A. Pascoe, ‘‘Encapsulators: A New Software Paradigm in Smalltalk 80,’’ inproc. of OOPSLA ’86, SIG-

PLAN, ACM, Sept. 1986.

[74] J.E. Stoy,”Denotational Semantics: The Scott-Stratchey Approach to Programming Language Theory,”, MIT

Press, 1979.

[75] A. Snyder, ‘‘Encapsulation and Inheritance in Object-Oriented Programming Languages,’’ ACM SIGPLAN

Notices, vol. 21, no. 11, pp. 38-45, Nov 1986.

[76] B. Stroustrup,The C++ Programming Language, Addison-Wesley, 1986.

[77] T.J. Teorey and T.B. Pinkerton, ‘‘A Comparative Analysis of Disk Scheduling Policies,’’ CACM, vol. 15,

no. 3, pp. 177-184, March 1972.

[78] R. D. Tennet, ‘‘The Denotational Semantics of Programming Languages,’’ CACM, vol. 19, no. 8, ACM, Au-

gust 1976.

[79] B. Thomsen, ‘‘A Calculus of Higher Order Communicating Systems,’’ 16th Symposium on Principles of Pro-

gramming Languages, pp. 143-154, Austin, Texas, Jan 11-13, 1989.

[80] C. Tomlinson and V. Singh, ‘‘Inheritance and Synchronization with Enabled Sets,’’ ACM SIGPLAN Notic-

es, Proceedings OOPSLA ’89, vol. 24, no. 10, pp. 103-112, Oct 1989.

[81] A. Tripathi and M. Aksit, “Communication, Scheduling, and Resource Management in SINA,” JOOP, pp. 24-

36, Nov/Dec 1988.

[82] D. Tsichritzis and O.M. Nierstrasz, ‘‘Application Development Using Objects,’’ Proc EUROINFO’88, pp.

15-23, North-Holland, 1988.

[83] F.W. Vaandrager, ‘‘Process Algebra Semantics of POOL,’’ inApplications of Process Algebra, ed. J.C. Ba-

eten, Cambridge Tracts in Theoretical Computer Science 17, pp. 173-236, Cambridge University Press, 1990.

[84] J. Van Den Bos and C. Laffra, “PROCOL: A Parallel Object Language with Protocols,” ACM SIGPLAN No-

tices, Proceedings OOPSLA ’89, vol. 24, no. 10, pp. 95-102, Oct 1989.

Page 144: Language Design Rationale and Semantic Framework for

References 129

[85] D. Walker, ‘‘π-calculus Semantics of Object-Oriented Programming Languages,’’ Report ECS-LFCS-90-

122, Laboratory for Foundations of Computer Science, Computer Science Department, University of Edin-

burgh, Oct. 1990.

[86] T. Watanabe and A. Yonezawa , “Reflection in an Object Oriented Concurrent Language,” ACM SIGPLAN

Notices, vol. 23, no. 11, pp. 306-315, 1988.

[87] P. Wegner, ‘‘Dimensions of Object-Based Language Design,’’ inProceedings OOPSLA ’87, SIGPLAN No-

tices, vol. 22, pp. 168-182, ACM, Orlando, Florida, December 1987.

[88] P. Wegner and S. B. Zdonik, ‘‘Inheritance as an Incremental Modification Mechanism or What Like Is and

Isn’t Like,’’ in Proceedings ECOOP’88, Lecture Notes in Computer Science, vol. 322, pp. 55-77, Springer

Verlag, 1988.

[89] R. J. Wirfs-Brock and R.E. Johnson, ‘‘Surveying Current Research in Object-Oriented Design,’’ Communi-

cations of the ACM, vol. 33, no. 9, pp. 104-123, Sept. 1990.

[90] Y. Yokote and M. Tokoro, “Concurrent Programming in ConcurrentSmalltalk,” inObject-Oriented Concur-

rent Programming, ed. M. Tokoro, pp. 129-158, The MIT press, Cambridge, Massachusetts, 1987.

[91] Y. Yokote and M. Tokoro, ‘‘Experience and Evolution of ConcurrentSmalltalk,’’ inProceedings OOPSLA

’87, SIGPLAN Notices, vol. 22, pp. 168-182, ACM, Orlando, Florida, December 1987.

[92] A. Yonezawa, E. Shibayama, T. Takada and Y. Honda, “Modelling and Programming in an Object-Oriented

Concurrent Language ABCL/1,” inObject-Oriented Concurrent Programming, ed. M. Tokoro, pp. 55-89,

The MIT Press, Cambridge, Massachusetts, 1987.