+ All Categories
Home > Documents > Concurrent Object-Oriented Programming

Concurrent Object-Oriented Programming

Date post: 11-Feb-2022
Category:
Upload: others
View: 6 times
Download: 0 times
Share this document with a friend
244
UNIVERSIDADE T ´ ECNICA DE LISBOA INSTITUTO SUPERIOR T ´ ECNICO Concurrent Object-Oriented Programming: Separation and Composition of Concerns using Design Patterns, Pattern Languages, and Object-Oriented Frameworks Ant´ onio Manuel Ferreira Rito da Silva Dissertation for the degree of Doctor of Philosophy in Informatics and Computer Engineering March 1999
Transcript

UNIVERSIDADE TECNICA DE LISBOAINSTITUTO SUPERIOR TECNICO

Concurrent Object-Oriented Programming:Separation and Composition of Concerns

using Design Patterns, Pattern Languages, andObject-Oriented Frameworks

Antonio Manuel Ferreira Rito da Silva

Dissertation for the degree of Doctor of Philosophy in

Informatics and Computer Engineering

March 1999

(This document contains the English translation of the thesis that was originally written in

Portuguese. I apologize if some sentences are harder to understand. Do not hesitate to send me

an e-mail. I’ll be grateful.

Antonio Rito Silva ([email protected]) )

Adviser

Prof. Doutor Pedro Manuel Moreira Vaz Antunes de Sousa

Professor Auxiliar do Departamento de Engenharia Informatica do Instituto Superior

Tecnico da Universidade Tecnica de Lisboa.

co-adviser

Prof. Doutor Jose Manuel da Costa Alves Marques

Professor Catedratico do Departamento de Engenharia Informatica do Instituto

Superior Tecnico da Universidade Tecnica de Lisboa.

Resumo

O desenvolvimento de programas concorrentes com objectos, na perspectiva da

engenharia de software, deve possuir um conjunto de qualidades que permitam con-

trolar as suas complexidades inerentes como o nao-determinismo.

Esta dissertacao contribui com a definicao de uma abordagem para a construcao

de programas concorrentes com objectos, alicercada na estrategia de dividir para con-

quistar, em que as facetas funcionais e nao-funcionais dos programas concorrentes

sao tratadas separadamente. A abordagem define padroes de desenho para tres fac-

etas nao-funcionais - Objecto Concorrente, Objecto Sincronizado e Objecto Recuperavel - e

padroes composicao para as combinacoes de facetas - Objecto Concorrente Sincroniza-

do, Objecto Sincronizado Recuperavel e Objecto Concorrente Sincronizado Recuperavel. Os

padroes de desenho e suas composicoes sao integrados num processo de desen-

volvimento incremental de programas concorrentes, descrito por uma linguagem de

padroes, em que a introducao de nao-determinismo e retardada por forma a facilitar

o teste e a depuracao de programas. Os padroes de desenho e suas composicoes sao

implementados por uma moldura de objectos possuindo uma arquitectura com tres

camadas e separacao de facetas que simplifica a adaptacao e a utilizacao pelo progra-

mador final.

Abstract

The development of concurrent object-oriented programs, from a software engi-

neering perspective, must possess a set of features to allow control of its inherent com-

plexities, such as non-determinism.

This dissertation contributes the definition of an approach for constructing con-

current object-oriented programs. The approach is rooted in a divide-and-conquer s-

trategy, in which functional and non-functional concerns of concurrent programs are

treated separately. The approach defines design patterns for three non-functional con-

cerns: Concurrent Object, Synchronized Object, and Recoverable Object. It also defines

composition patterns for combining the concerns: Concurrent Synchronized Object, Syn-

chronized Recoverable Object, and Concurrent Synchronized Recoverable Object. The design

patterns and their compositions are integrated in an incremental development process

for concurrent programs, which is described by a pattern language. The introduction

of non-determinism in the development process is delayed so as to facilitate testing and

debugging of programs. The design patterns and their compositions are implemented

by an object-oriented framework. The framework’s architecture is organized in three

layers dealing with concerns separation. This architecture simplifies customization

and use by the end programmer.

Keywords

Concurrent Object-Oriented Programming

Design Patterns and Pattern Languages

Object-Oriented Frameworks

Separation and Composition of Concerns

Software Architectures

Object-Oriented Analysis and Design Methods

Palavras chave

Programacao Concorrente com Objectos

Padroes de Desenho e Linguagens de Padroes

Molduras de Objectos

Separacao e Composicao de Facetas

Arquitecturas de Software

Metodos de Analise e Desenho com Objectos

Acknowledgments

I would like to express to my adviser, Prof. Pedro Sousa, my heartfelt thanks. It

was Prof. Pedro Sousa who encouraged me to begin this work. Prof. Pedro Sousa

believed in its success even when I was still walking the first steps in an area new to

me. It was with Prof. Pedro Sousa that through the last few years I have discussed my

work. The results of those discussions is indelibly engraved in the final work.

To my co-adviser, Prof. Jose Alves Marques, I would like to express my thanks for

his support during the initial phase of this work and for having made possible for it

to occur in a context where I was free to experiment with various trends and conclude

my research.

I would like to thank all who have collaborated and believed in the DASCo project

(Development of Distributed Applications with Separation of Concerns) and that, in its con-

text, have carried out their research work.

I am especially grateful to all who directly participated in the concurrency aspect

of DASCo: Eng. Joao Pereira for his cooperation in identifying concurrency policies in

transactional systems (Pereira, 1994); Eng. Luıs Gil and Eng. Joao Martins for imple-

menting the initial version of the object-oriented framework for concurrency (Martins

& Gil, 1996); Eng. Daniel Silva and Eng. Carlos Alves for using the object-oriented

framework in the construction of a cooperative work system (Alves & Silva, 1997); and

Eng. Joao Cruz for his work on concurrent programs instrumentation (Cruz, 1997).

I thank all those with whom I have discussed the DASCo approach concerning its

principles and strategy. I am especially grateful to Eng. Franciso Rosa, Eng. Teresa

Goncalves, and Eng. Miguel Antunes for their work, while master course students,

on the partitioning aspect of DASCo and for the fruitful discussions that allowed the

approach’s ideas and concepts to be exercised.

I thank Eng. David Matos for the many times he read my papers.

Prof. Luıs Rodriges, Eng. Joao Pereira, and Dr. Ceu Ribeiro deserve a special men-

tion for generously reading the initial versions of this dissertation. Their comments

helped me clarify the presentation.

I would also like to thank all the members of INESC’s Software Engineering and

Distributed Systems Groups with whom it was my pleasure to work with all these

years.

A final note must go to the role Internet has played during all my PhD work. The

virtual and global environment it defines, allowed me to obtain the information I need-

ed, to contact other researchers, and to disseminate my work.

I thank INESC for the means put at my disposal and IST for the sabbatical.

I thank Ceu, Tininha, and Ze Manel, for their support and permanence through the

years.

Lisboa, March 1999

Antonio Manuel Ferreira Rito da Silva

em memoria de meu pai

para a minha mae

para a eva

Contents

I Introduction 1

1 Prologue 3

1.1 Software Engineering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.2 Quality Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

1.3 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.4 Dissertation’s Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2 Concurrent Object-oriented Programming 11

2.1 Concurrency and Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2.2 Categorizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.2.1 Object Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.2.2 Concurrency Granularity . . . . . . . . . . . . . . . . . . . . . . . 13

2.2.3 Concurrency Support Constructs . . . . . . . . . . . . . . . . . . . 14

2.3 Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.4 Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.4.1 Inheritance and Synchronization . . . . . . . . . . . . . . . . . . . 19

2.4.2 Reusability and Incremental Development . . . . . . . . . . . . . 22

2.5 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

i

2.5.1 Expressiveness and Simplicity . . . . . . . . . . . . . . . . . . . . 23

2.5.2 Reusability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

2.5.3 Incremental Development . . . . . . . . . . . . . . . . . . . . . . . 27

2.6 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

3 Separation and Composition of Concerns 31

3.1 Basic Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

3.1.1 Design Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

3.1.2 Pattern Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

3.1.3 Object-oriented Framework . . . . . . . . . . . . . . . . . . . . . . 37

3.2 Separation and Composition of Concerns . . . . . . . . . . . . . . . . . . 38

3.2.1 Concerns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

3.2.2 Design Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

3.2.3 Pattern Composition . . . . . . . . . . . . . . . . . . . . . . . . . . 43

3.2.4 Pattern Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

3.2.5 Three-layered Object-oriented Framework . . . . . . . . . . . . . 45

3.2.6 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

3.3 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

3.3.1 Languages or Class Libraries . . . . . . . . . . . . . . . . . . . . . 50

3.3.2 Unification or Separation . . . . . . . . . . . . . . . . . . . . . . . 51

3.3.3 Approaches with Separation of Concerns . . . . . . . . . . . . . . 54

3.4 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

ii

II Separation of Concerns 59

4 Concurrent Object Pattern 61

4.1 Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

4.2 Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

4.3 Forces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

4.4 Structure and Participants . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

4.5 Collaborations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

4.6 Forces Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

4.6.1 Expressiveness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

4.6.1.1 Sequential Object . . . . . . . . . . . . . . . . . . . . . . 67

4.6.1.2 Concurrent Object . . . . . . . . . . . . . . . . . . . . . . 69

4.6.1.3 Non-Concurrent Object . . . . . . . . . . . . . . . . . . . 70

4.6.1.4 Communication Variants . . . . . . . . . . . . . . . . . . 70

4.6.1.5 Concurrent Object: Explicit Creation . . . . . . . . . . . 71

4.6.2 Modularity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

4.6.3 Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

4.6.4 Reusability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

4.7 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

4.8 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

5 Synchronized Object Pattern 77

5.1 Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

5.2 Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

5.3 Forces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

iii

5.4 Structure and Participants . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

5.5 Collaborations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

5.6 Forces Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

5.6.1 Expressiveness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

5.6.1.1 Readers/Writers Policy . . . . . . . . . . . . . . . . . . . 87

5.6.1.2 Dynamic Priority Policy . . . . . . . . . . . . . . . . . . 90

5.6.1.3 Producer/Consumer Policy . . . . . . . . . . . . . . . . 91

5.6.1.4 Synchronization Counters . . . . . . . . . . . . . . . . . 92

5.6.1.5 Enabled Sets . . . . . . . . . . . . . . . . . . . . . . . . . 93

5.6.2 Modularity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

5.6.3 Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

5.6.4 Reusability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

5.7 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

5.8 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

6 Recoverable Object Pattern 103

6.1 Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

6.2 Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

6.3 Forces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

6.4 Structure and Participants . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

6.5 Collaborations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

6.6 Forces Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

6.6.1 Expressiveness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

6.6.1.1 Update-In-Place and Deferred-Update Policies . . . . . 108

iv

6.6.1.2 Object Copy and Compensating Operations . . . . . . . 109

6.6.2 Modularity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

6.6.3 Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

6.6.4 Reusability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

6.7 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

6.8 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

III Composition of Concerns 113

7 Pattern Composition 115

7.1 Concurrent Synchronized Object Pattern . . . . . . . . . . . . . . . . . . . . 115

7.1.1 Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

7.1.2 Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

7.1.3 Forces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118

7.1.4 Structure and Participants . . . . . . . . . . . . . . . . . . . . . . . 118

7.1.5 Collaborations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

7.1.6 Forces Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

7.1.6.1 Expressiveness . . . . . . . . . . . . . . . . . . . . . . . . 122

7.1.6.2 Modularity . . . . . . . . . . . . . . . . . . . . . . . . . . 122

7.1.6.3 Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . 125

7.1.6.4 Reusability . . . . . . . . . . . . . . . . . . . . . . . . . . 125

7.1.6.5 Consistency . . . . . . . . . . . . . . . . . . . . . . . . . . 125

7.2 Synchronized Recoverable Object Pattern . . . . . . . . . . . . . . . . . . . . 125

7.2.1 Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

v

7.2.2 Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

7.2.3 Forces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

7.2.4 Structure and Participants . . . . . . . . . . . . . . . . . . . . . . . 127

7.2.5 Collaborations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

7.2.6 Forces Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

7.3 Concurrent Synchronized Recoverable Object Pattern. . . . . . . . . . . . . . 130

7.3.1 Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

7.3.2 Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

7.3.3 Forces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

7.3.4 Structure e Participants . . . . . . . . . . . . . . . . . . . . . . . . 132

7.3.5 Collaborations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

7.3.6 Forces Resolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

7.3.6.1 Expressiveness . . . . . . . . . . . . . . . . . . . . . . . . 135

7.3.6.2 Modularity . . . . . . . . . . . . . . . . . . . . . . . . . . 135

7.4 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

7.5 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

8 Pattern Language 141

8.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

8.1.1 Process Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

8.1.2 Administrator Program . . . . . . . . . . . . . . . . . . . . . . . . 142

8.2 Functionality Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

8.2.1 Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

8.2.2 Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

vi

8.2.3 Forces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

8.2.4 Strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

8.2.5 Resulting Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

8.2.6 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

8.3 Concurrency Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

8.3.1 Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

8.3.2 Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

8.3.3 Forces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

8.3.4 Strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

8.3.5 Resulting Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

8.3.6 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

8.4 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

8.5 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

9 Object-oriented Framework 155

9.1 Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155

9.2 Object Concurrency, Synchronization and Recovery . . . . . . . . . . . . 158

9.2.1 Concern Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

9.2.1.1 Concurrency Concern . . . . . . . . . . . . . . . . . . . . 161

9.2.1.2 Synchronization Concern . . . . . . . . . . . . . . . . . . 163

9.2.1.3 Recovery Concern . . . . . . . . . . . . . . . . . . . . . . 165

9.2.2 Composition Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

9.2.2.1 Synchronized Object Composition . . . . . . . . . . . . . 167

9.2.2.2 Concurrent Synchronized Object Composition . . . . . 169

vii

9.2.3 Application Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . 173

9.3 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

9.4 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180

IV Conclusion 183

10 Results 185

11 Future Work 191

11.1 Coordination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

11.2 Role-based Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194

12 Epilogue 197

12.1 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197

12.2 Achievement of Goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199

12.3 Final Remarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201

A Bibliography 203

viii

List of Figures

2.1 Synchronization example: synchronization with enabled sets. . . . . . . 20

2.2 Synchronization example: synchronization with abstract states. . . . . . 20

2.3 Synchronization example: synchronization with guards. . . . . . . . . . 21

2.4 Synchronization example: composition of synchronization code. . . . . . 21

3.1 The Proxy Pattern’s Structure . . . . . . . . . . . . . . . . . . . . . . . . . 34

3.2 Architecture of the Three-layered Object-oriented Framework with Sep-

aration of Concerns. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

4.1 Structure of the Concurrent Object pattern. . . . . . . . . . . . . . . . . . . 64

4.2 Collaborations in the Concurrent Object pattern: invocation and acquisi-

tion of results. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

4.3 Collaborations in the Concurrent Object pattern: invocation execution. . . 66

4.4 Structure Specialization for Sequential Object. . . . . . . . . . . . . . . . 68

4.5 Collaboration Specialization for Sequential Object. . . . . . . . . . . . . . 68

4.6 Collaborations Specialization or Concurrent Object. . . . . . . . . . . . . 69

5.1 Structure of the Synchronized Object pattern. . . . . . . . . . . . . . . . . . 81

5.2 Synchronized Object pattern collaborations: generic part. . . . . . . . . . . 83

5.3 Collaborations of the Synchronized Object pattern: policy-specific part. . . 85

ix

5.4 Specialization for Pessimist and Optimist Policies. . . . . . . . . . . . . . 86

5.5 Specialization for Readers/Writers (Pessimist). . . . . . . . . . . . . . . . 87

5.6 Specialization for Readers/Writers (Optimist). . . . . . . . . . . . . . . . 89

5.7 Specialization for Dynamic Priority. . . . . . . . . . . . . . . . . . . . . . 90

5.8 Specialization for Producer/Consumer. . . . . . . . . . . . . . . . . . . . 92

5.9 Specializations of Class Synchronization Data. . . . . . . . . . . . . 94

6.1 Structure of the Recoverable Object pattern. . . . . . . . . . . . . . . . . . . 106

6.2 Collaborations of the Recoverable Object pattern. . . . . . . . . . . . . . . . 107

7.1 Conflict Matrix of the Synchronized Concurrent Object Pattern. . . . . . . . 117

7.2 Structure of the Concurrent Synchronized Object Pattern. . . . . . . . . . . 119

7.3 Collaborations of the Concurrent Synchronized Object Pattern. . . . . . . . 121

7.4 Collaborations of the Concurrent Synchronized Object Pattern: immediate

association. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

7.5 Collaborations of the Concurrent Synchronized Object Pattern: lazy asso-

ciation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

7.6 Structure of the Synchronized Recoverable Object Pattern. . . . . . . . . . . 128

7.7 Collaborations of the Synchronized Recoverable Object Pattern. . . . . . . . 129

7.8 Structure of the the Concurrent Synchronized Recoverable Object Pattern. . 132

7.9 Collaborations of the Concurrent Synchronized Recoverable Object Pattern:

immediate association. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136

7.10 Collaborations of the Concurrent Synchronized Recoverable Object Pattern:

lazy association. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

8.1 Administrator Program. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

x

8.2 Administrator Program: Class Diagram for the Sequential Version. . . . 146

8.3 Administrator Program: Class Diagram (Concurrent Version). . . . . . . 151

9.1 Three-layered Architecture with Separation of Concerns. . . . . . . . . . 156

9.2 Framework for Object Concurrency, Synchronization, and Recovery. . . 159

9.3 Concern Layer: CONCURRENT OBJECT Component. . . . . . . . . . . . . 160

9.4 Concern Layer: SYNCHRONIZED OBJECT Component. . . . . . . . . . . 163

9.5 Concern Layer: RECOVERABLE OBJECT Component. . . . . . . . . . . . 165

9.6 Composition Layer: COMPOSITION SYNCHRONIZED OBJECT Compo-

nent. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

9.7 Synchronization Interface Composition Class: Constructor. . 168

9.8 Synchronization Interface Composition Class: preControl. 169

9.9 Synchronized Invocation Composition Class: delSyncInvo-

cation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

9.10 Composition Layer: COMPOSITION CONCURRENT SYNCHRONIZED

OBJECT Component. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

9.11 Concurrency Synchronization Interface Composition

Class: Constructor (fragment). . . . . . . . . . . . . . . . . . . . . . . . . . 172

9.12 Concurrency Synchronization Associator Class: preControl. 174

9.13 Concurrency Synchronized Invocation Composition Class:

delSyncInvocation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175

9.14 Class Buffer enriched with concerns. . . . . . . . . . . . . . . . . . . . . 175

9.15 Synchronized Buffer Class: Definition (fragment) and get. . . . . . 176

9.16 Concurrent Synchronized Buffer Class: Definition (fragment)

and get. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

xi

xii

Part I

Introduction

1

1Prologue

Programming is a complex activity. Various techniques, tools, and methods have

been proposed to help programmers, such as, structured techniques (Martin & Mc-

Clure, 1988) and object-oriented analysis and design methods (Hutt, 1994b).

Separation of concerns is considered a key technique in software engineering (Par-

nas, 1978; Ghezzi et al., 1991; Jackson, 1995). This technique consists of treating sepa-

rately different aspects of program construction in order to control complexity, in ac-

cordance with a divide-and-conquer strategy. For instance, the separation between a

program’s functional and non-functional concerns allows the construction of an initial

version supporting only its functionality in terms of expected input and output, and its

later enrichment to support other aspects, such as performance, reliability and compu-

tational constraints. Problems handled by functional and non-functional concerns are

specified, respectively, by a program’s functional and non-functional requirements.

The construction of concurrent programs is especially complex due mainly to the

inherent non-determinism of their execution, which makes it difficult to repeat test s-

cenarios. It should be noted that the execution order of two concurrent activities is

influenced by external programming conditions, such as processor load and interrup-

tions.

This dissertation presents an approach for constructing concurrent program-

s which separately handles, during the development process, functional and non-

functional concerns. The approach defines solutions for each non-functional concern

related to concurrency, such as object synchronization, and integrates those solution-

s as well as their composition in an incremental development process of concurrent

programs. In addition, the approach allows the most appropriate solution for each

3

4 CHAPTER 1. PROLOGUE

concern to be customized by the programmer to take into account the specific needs

of the program being built. Furthermore, pre-defined customizations are offered for

each concern. The programmer is able use them without needing to be aware of the

underlying complexity associated with both the problem the concern deals with and

the construction of the solution. Concern solutions are based on micro-architectures of

cooperating objects which may be applied and customized in various programs.

1.1 Software Engineering

As defined by Parnas(1978), software engineering deals with the construction of

systems whose complexity requires the intervention of teams of engineers. Due to the

interaction and cooperation among team members, software engineering must have

a set of principles applicable, not only to the developed products, but also to their

development process.1 Software engineering principles are the basis for the methods,

techniques and tools used by the software engineer.

Ghezzi et al.(1991) introduces seven software engineering principles:

� Rigor and Formalism. Construction of quality programs is achieved through a

rigorous approach consisting of a set of well-defined, clear, and correct stages.

Methods and techniques used by a rigorous approach are usually based on a

combination of both theoretical and experimental results. The use of a mathe-

matical formalism allows a high level of rigor, but it is possible to define a set of

correct stages without the need to manage and evaluate the development process

only through a mathematical formalism.

� Separation of concerns. Separation of concerns consists of separately handling

different aspects of program construction so that the programmer is able to deal

with each aspect at a time. Only by isolating the different aspects is it possible to

control complexity. Moreover, concern separation allows separation of responsi-

bilities, thus improving teamwork. Concern separation may be applied in several

1These principles are less relevant when applied in the context of application development by a singleprogrammer.

1.1. SOFTWARE ENGINEERING 5

ways: separation in time, in which temporal planning is carried out for the dif-

ferent activities; separation in terms of qualities, in which each program quality,

such as functional correctness or efficiency, is handled separately; separation in

terms of views, in which a program is analyzed from different viewpoints, such

as dataflow or flow of control; and, separation in terms of parts, in which a pro-

gram is divided in modules.

� Modularity. Dividing a program into modules allows the separation of concerns

to be applied in two stages: handling of a module’s details and handling of inter-

module relationships. High internal module cohesion and low inter-module cou-

pling are at the center of the previous two stages. Modularity allows the decom-

position of a program into modules, the composition of a program from existing

modules, and understanding each part of a program separately.

� Abstraction. Abstraction is a process in which relevant aspects are identified and

details are ignored. A program may be perceived at different abstraction levels.

For instance, abstractions relevant for a program’s user are different from those

relevant for its programmer. Abstraction helps in complexity management as

it allows specifications to be built at an abstraction level ignoring some aspects.

Later on, specifications are implemented at a lower abstraction level in which the

aspects previously ignored become relevant. Programming languages are typical

examples of tools containing abstractions implemented by lower level abstrac-

tions generated by the language’s compiler.

� Anticipation of Change. Programs must evolve because of requirements change.

A program must be prepared to anticipate change in order to reduce its impact.

For that, the parts most likely to evolve must be identified and isolated, thus lim-

iting the number of changes. The identification of a program’s future evolutions

must be carried out at the requirements gathering stage, while the isolation of

parts to be changed may be done using modularity.

� Generality. When solving a problem it is wise to identify a more general problem

that may be hidden behind the problem at hand. The construction or use of a

6 CHAPTER 1. PROLOGUE

tool or method to solve a more general problem may be reused in the context of

different programs.

� Incrementallity. The development process should be incremental. A program

is built in successive increments, each of which provides a closer approximation

to the complete satisfaction of the final goals. Incremental development allows

incremental testing and debugging of a program. Furthermore, it allows early

interaction with the users, thus supporting requirements gathering.

1.2 Quality Requirements

From a software engineering perspective, and based on the aforementioned prin-

ciples, an approach for the development of concurrent programs must satisfy, in ad-

dition to functional and non-functional requirements, a set of quality requirements.

Thus, the definition of an approach for the development of concurrent programs, ca-

pable of satisfying the following quality requirements, constitutes the main goal of this

dissertation:

� Separation of Concerns. The complexity associated with the development of

concurrent programs must be handled through a divided-and-conquer strategy.

The initial separation is between a program’s functionality, defined based on the

program’s functional requirements, and concurrency, defined based on the pro-

gram’s non-functional requirements. Moreover, it must be possible to identify

various concurrency concerns, such as object synchronization, and handle them

also separately.

� Modularity. Solutions for each concern must be encapsulated in highly cohe-

sive modules presenting low coupling between each other, i.e., modularity is the

structural support for concern separation.

� Generality. Each module must offer a more general solution than the required by

each program’s specific problem, so that it may be reused. For instance, a module

for the object synchronization concern must support different synchronization

1.2. QUALITY REQUIREMENTS 7

policies, such as the readers/writers policy or the producer/consumer policy,

and not just the object synchronization policy required by the specific problem.

� Anticipation of Change. Each module must isolate the parts of the concern solu-

tion which are liable to change in order to reduce the impact of changes in other

modules. For instance, a module for the object synchronization concern must

isolate from other modules the consequences of future synchronization policy

changes.

� Abstraction. It must be possible to develop concurrent programs while ignoring

solution details of each concern. There must exist pre-defined high-abstraction

level module instantiations ready to be used be programmers through a simple

interface. However, it must be also possible for programmers to work, if they so

desire, at a lower abstraction level through the creation of module instantiations

customized to their specific needs.

� Incrementallity. The development of concurrent programs must be incremen-

tal, in order to delay introduction of concerns causing non-determinism, for they

make testing and debugging more difficult. Functional requirements must be sat-

isfied in the initial stages to allow their endorsement by the users. From this per-

spective, in which functionality is developed first and concurrency is introduced

at a later time, increments are said to be horizontal, in contrast to functional in-

crements, which are said to be vertical.

� Documentation. Modules must be documented so that it is possible to under-

stand their function at different abstraction levels. For instance, it must be pos-

sible to understand a module’s collaboration structure independently from its

implementation. Documentation must allow different kinds of module users, ac-

cording to the required knowledge level.

Satisfaction of these quality requirements by the approach implies a rigorous set

of well-defined and clear stages. The correctness of these stages must result from an

extensive analysis of existing solutions for each concern. The application of the results

of this analysis will reflect itself in each module’s correction.

8 CHAPTER 1. PROLOGUE

1.3 Results

The results obtained with the work described in this dissertation were:

� Definition of an approach for separation and composition of concerns (Silva et al.,

1995). This approach identifies various concurrency concerns (Silva et al., 1996d;

Silva, 1997a; Silva et al., 1997b; Silva, 1997b).

� Definition of constructs for concurrency concerns (Silva et al., 1996d; Silva, 1997a;

Silva et al., 1997b; Silva, 1997b). These constructs have the following properties:

modularity, abstraction, anticipation of change, and generality. As a consequence

of their modularity, constructs are easily composed with each other (Silva, 1998).

� Definition of an incremental development process that builds a program version

supporting its functionality and allows later introduction of concurrency con-

cerns (Silva, 1997b).

� Definition of a three-layered architecture supporting separation and composition

of concerns and its implementation as an object-oriented framework (Silva, 1998;

Silva et al., 1999).

� Documentation of the object-oriented framework using design and composition

patterns (Silva, 1998; Silva et al., 1999).

1.4 Dissertation’s Structure

This dissertation consists of four parts.

Part I introduces the problem and presents the proposed approach:

� Chapter 1 introduces software engineering and sets the quality requirements

which, in this discipline, will have to be satisfied by program development ap-

proaches.

1.4. DISSERTATION’S STRUCTURE 9

� Chapter 2 categorizes different approaches for the integration of concurrent and

object-oriented programming. It also defines the requirements these approaches

must satisfy and identifies problems which appear when aiming at satisfying

those requirements. This chapter ends with an evaluation of the related work, in

terms of requirement satisfaction and resolution of identified problems.

� Chapter 3 presents the approach to concurrent object-oriented programming

based on separation of concerns and using design patterns. This chapter con-

tains an evaluation of other approaches for concurrent object-oriented program-

ming. Special emphasis is put on approaches with separation of concerns. These

approaches will be revisited in the related work sections of chapters 4-9.

Part II presents the separation of concerns in terms of design patterns. Design pat-

terns describe constructs for concurrency concerns. Solutions described by these pat-

terns have the properties of expressiveness, modularity, encapsulation, and reusability,

which satisfy some of the quality requirements, from a software engineering perspec-

tive, required by an approach for the development of concurrent programs. Three

object concurrency concerns are considered: Chapter 4 presents the Concurrent Object

pattern; Chapter 5 presents the Synchronized Object pattern; and Chapter 6 presents the

Recoverable Object pattern.

Part III presents composition of concerns in terms of composition of design pat-

terns, of a pattern language, and of an object-oriented framework:

� Chapter 7 presents the composition of design patterns. Each composition pattern

describes the composition of concern constructs. Solutions described by composi-

tion patterns possess, in addition to the properties of design patterns, expressive-

ness, modularity, encapsulation, and reusability, the property of consistency. This

new property ensures consistent combination of design patterns, both in struc-

tural and semantic terms. Three composition patterns are presented: Concurrent

Synchronized Object, Synchronized Recoverable Object, and Concurrent Synchronized

Recoverable Object.

10 CHAPTER 1. PROLOGUE

� Chapter 8 presents the pattern language which describes how design and com-

position patterns should be applied in an incremental development process of

concurrent object-oriented programs. A process integrating this pattern language

meets some of the quality requirements required in the context of software engi-

neering, among which, anticipation of change and incrementallity.

� Chapter 9 presents an object-oriented framework, written in C++, which imple-

ments design and composition patterns. The object-oriented framework follows

a three-layered architecture with separation of concerns, which is independen-

t from the implementation environment. This architecture simplifies the use of

patterns by the final programmer.

Finally, in Part IV, Chapter 10 presents the achieved results, Chapter 11 presents

future work, and Chapter 12 revisits this dissertation’s goals and their solutions using

the proposed approach.

2Concurrent

Object-orientedProgramming

This chapter presents problems relating to the integration of concurrent and object-

oriented programming. After a brief introduction to concurrency and objects, in sec-

tion 2.1, section 2.2 identifies some existing categorizations of approaches integrating

concurrency and objects. In section 2.3, the results of this identification are analyzed.

Also in this section are stated the requirements that approaches integrating concurren-

cy and objects must satisfy. In section 2.4, problems appearing when seeking to satisfy

the requirements stated in the previous section are identified. In section 2.5, various

existing approaches for concurrent object-oriented programming are discussed, taking

into account the identified requirements and problems. Finally, section 2.6 presents

conclusions.

2.1 Concurrency and Objects

Concurrent programming should express and control the execution, synchroniza-

tion, and communication of independent and conceptually simultaneous activities.1

Object-oriented programming models a problem by decomposing it into a set of in-

dependent entities and their corresponding interactions. These entities, called objects,

hold exclusive access to their internal state and collaborate with each other through

message exchange. The object-oriented paradigm owes its modeling power to three

1An activity should be understood as a flow of control such as a thread.

11

12 CHAPTER 2. CONCURRENT OBJECT-ORIENTED PROGRAMMING

features (Wegner, 1987; Wegner, 1992):

� Object: encapsulates its internal attributes confining accesses to a group of oper-

ations;

� Class: defines the internal attributes and behavior common to a set of objects

called class instances.

� Inheritance: defines new classes by incrementally modifying existing ones.

There are several reasons to integrate concurrent and object-oriented program-

ming (Tomlinson & Scheevel, 1989; Papathomas, 1995):

� To increase the expressiveness of object-oriented programming in order to easily

model inherently concurrent aspects of problems.

� To take advantage of the reusability feature, inherent to the object-oriented

paradigm, in the development of concurrent programs.

� To take advantage of physical parallelism in object implementation in order to

increase program performance.

However, it has been verified that the integration of concurrent and object-oriented

programming is far from trivial.

2.2 Categorizations

To analyze the various integration approaches between concurrent and object-

oriented programming, several categorizations have been proposed. These categoriza-

tions classify approaches in terms of object model, of object concurrency granularity,

and of concurrency support constructs.

2.2. CATEGORIZATIONS 13

2.2.1 Object Model

Papathomas & Nierstrasz(1991) and again Papathomas(1995) propose a categoriza-

tion for concurrent programming approaches in terms of object model. In the object

model’s definition two kinds of objects are considered: active objects and passive ob-

jects. An object is active if it controls concurrent invocations, otherwise it is said to be

passive.2 Passive objects are those which unconditionally accept invocations. Three

object models are considered, according to the kind of objects used: active, passive, or

both.

� In the orthogonal model all objects are passive.

� In the homogeneous model all objects are active. For instance, in the Rosette lan-

guage (Tomlinson & Singh, 1989) each object defines the set of operations which

in each moment it may accept for execution, called enabled set.

� The heterogeneous model allows both active and passive objects. Thus, to pre-

serve their consistency, passive objects must be in an active object’s synchroniza-

tion context. For instance, the Argus system (Liskov, 1988) has active objects,

guardians, which synchronize accesses to a group of passive objects. It is the Ar-

gus architecture itself which guarantees the consistency of passive objects, for all

accesses to a group of passive objects must be through invocations to the corre-

sponding guardian.

2.2.2 Concurrency Granularity

Wegner(1987; 1992) defines three categories regarding an object’s concurrency

granularity: inter-object, quasi-intra-object, and intra-object3.

2It should be noted that this definition is somehow different from the more usual active object def-inition given in the model of Actors (Agha, 1986). In this model, an active object is one possessing aninternal activity. Nevertheless, that activity is usually used to control concurrent invocations and, thus,this definition corresponds in fact to an implementation of an active object as presented by Papath-omas & Nierstrasz.

3Actually, Wegner refers to sequential, quasi-concurrent, and concurrent objects, respectively. Nameshave been modified to avoid nomenclature conflicts within this dissertation, in section 2.2.3, for relation-ships between objects and the activities executing their invocations.

14 CHAPTER 2. CONCURRENT OBJECT-ORIENTED PROGRAMMING

� Inter-object granularity allows only the execution in an object of a single invoca-

tion at a time. It is not possible to interleave the execution of several invocations.

If all objects have inter-object granularity the only concurrency in a program is

between objects.

� Quasi-intra-object granularity only allows the execution of a single invocation at

a time, but if the current execution blocks, then another invocation may initiate

or resume its execution. It is possible to interleave the execution of several in-

vocations. For instance, the synchronized objects of the Java language (Arnold

& Gosling, 1996) have quasi-intra-object granularity: they constitute a moni-

tor (Hoare, 1974).

� Intra-object granularity allows concurrent execution of several invocations in an

object and, thus, interleaving of the execution of their actions.

2.2.3 Concurrency Support Constructs

Objects possess three types of concurrency support constructs: object synchroniza-

tion constructs, object concurrency constructs, and object interaction constructs (Pa-

pathomas & Nierstrasz, 1991; Papathomas, 1995). Object synchronization constructs

control the execution order of object invocations. Object concurrency constructs are

responsible for creating, managing, and destroying activities executing object invoca-

tions. Object interaction constructs are responsible for the synchronization between

client and server objects during an invocation.

There are several types of object synchronization constructs:

� In unconditional acceptance, objects do not have object synchronization construct-

s of their own. Synchronization is orthogonal to the objects, i.e., objects are

passive. Thus, objects must use primitive synchronization constructs such as

semaphores (Dijkstra, 1968) or monitors (Hoare, 1974) to control accesses. For in-

stance, the Smalltalk language (Goldberg & Robson, 1983) offers synchronization

primitives, semaphores, which the programmer may use to synchronize invoca-

tions to an object’s operations.

2.2. CATEGORIZATIONS 15

� In conditional acceptance, objects integrate synchronization constructs which may

delay invocation execution in order to control execution order. Synchronization

is not orthogonal to the objects, i.e., objects are active. There are several constructs

for conditional acceptance:

– In explicit acceptance, there is a construct, accept, which denotes invocation

acceptance. Variations of this construct allow different expressive power

when specifying the next invocation to be accepted. For instance, the ob-

jects of the Eiffel// language (Caromel, 1990a; Caromel, 1990b) have a part,

called body, which defines which invocations should be accepted in each

situation.

– Activation conditions define the states in which operation execution can be

accepted. For instance, path expressions (Campbell & Habermann, 1974) de-

fine, through a regular expression, the sequences of operations/invocations

which may be accepted by an object.

A concurrent program executes in the presence of several activities. Different con-

struct types exist to create or destroy activities:

� Non-concurrent objects do not have activity creation, management, or destruction

constructs of their own. These objects are passive for they do not control activity

creation and management. In this situation, an object uses the activity associated

with the invocation request. If objects want to generate an activity they have to

use primitive activity generation constructs provided by a threads library. For

instance, in the Smalltalk and Java languages (Arnold & Gosling, 1996) objects

execute using the invoker’s activity.

� Sequential objects define a single internal activity responsible for invocation exe-

cution. For instance, ADA tasks (American National Standards Institute, 1983)

have a single internal activity which accepts and executes invocations.

� Concurrent objects have several internal activities for invocation execution. There

are various kinds of constructs for creating several internal activities:

16 CHAPTER 2. CONCURRENT OBJECT-ORIENTED PROGRAMMING

– A new activity is created when a concurrent object receives a message. Neu-

sius(1991) proposes an execution model in which a new activity is implicitly

created for each operation invocation. In contrast, primitive become of Ac-

tors languages is responsible for explicitly creating a new activity when a

message is received.

– An internal activity is explicitly created and destroyed by the concurrent object

without creation being triggered by an invocation. For instance, the SR lan-

guage (Andrews et al., 1988) has a cobegin coend construct (Andrews &

Schneider, 1983) associated with the execution of concurrent activities.

Non-concurrent and concurrent objects have intra-object granularity, while se-

quential objects have inter-object granularity.

Two construct types for object interaction exist:

� In constructs supporting one-way message passing, information flows from the in-

voker to the invoked object. These constructs require the definition of higher

level protocols to associate replies with requests. One-way message passing may

be synchronous or asynchronous. For instance, the CSP language (Hoare, 1985)

uses synchronous one-way message passing.

� In constructs supporting request/reply interaction, a reply is associated with each

request. If the request is a procedure call then the client waits until a reply is

received. However, by using future variables (Yonezawa et al., 1987) a client may

continue executing concurrently with the server object using, later on, the future

variable to synchronize itself with invocation termination and receive its results.

For instance, the Eiffel// language allows the use of future variables.

2.3 Requirements

The integration of concurrent and object-oriented programming must preserve the

advantages of objects regarding reusability (Wegner, 1987; Wegner, 1992) and support

2.3. REQUIREMENTS 17

for an incremental development process (Hutt, 1994a; Hutt, 1994b). Thus, encapsu-

lating concurrency and synchronization within an object allows changing its imple-

mentation without the need for altering its clients, for changes are not propagated.

Moreover, encapsulation facilitates incremental development for it is possible to incre-

mentally introduce concurrency and synchronization in an object, independently from

its clients.

This dissertation sets as goal the fulfillment of the three main requirements for the

integration of concurrency and objects:

� Expressiveness and Simplicity. The integration must offer object concurrency, syn-

chronization, and interaction support constructs with high expressive power. For

instance, regarding object concurrency, non-concurrent, sequential, and concur-

rent objects must be supported. Nevertheless, expressiveness should be achieved

with simplicity.4 Thus, constructs provided to the programmer should result

from a compromise between expressiveness and simplicity.

Henceforth, a construct’s expressiveness will refer to its capacity for supporting

a set of policies. For instance, synchronization based on the distinction between

read and write operations is a readers/writers object synchronization policy.

� Reusability. The integration must allow the construction of concurrent program-

s by using traditional reuse mechanisms of object-oriented programming: class

inheritance and object composition (Gamma et al., 1994; Johnson & Foote, 1988).

Object reusability must include separate reuse of functionality, concurrency, syn-

chronization, and interaction.

� Incremental development. The integration must support incremental development

of concurrent programs. Concurrent programs are difficult to test and debug due

to the non-determinism inherent to their execution. Incremental development

must allow incremental program construction in which functionality is devel-

oped first and tested in a sequential environment. Object concurrency, synchro-

nization, and interaction are introduced later. It should be noted that incremental

4For instance, it is well known that semaphores can emulate monitors and vice-versa. However, suchemulations are complex.

18 CHAPTER 2. CONCURRENT OBJECT-ORIENTED PROGRAMMING

development assumes the reusability requirement, but the reverse is not neces-

sarily true.

In various papers by Papathomas & Nierstrasz (Papathomas & Nierstrasz, 1991;

Nierstrasz, 1993; Papathomas, 1995) five requirements are presented that a language

integrating concurrent and object-oriented programming must satisfy. This set of re-

quirements is contained in the three aforementioned requirements. These five require-

ments emphasize reusability:

1. Mutual exclusion. An object’s internal state must be automatically protected from

concurrent invocations without the need for client objects to synchronize among

themselves.

2. Internal concurrency. An object should be able to process several invocations con-

currently. Internal concurrency must be transparent to client objects so that it can

be changed independently from them.

3. Request scheduling transparency. A server object must be able to delay request exe-

cution based on the type of request and on object state. Request execution delays

must be transparent to client objects so that scheduling policies can be changed

without affecting clients (the scheduling policy is, in fact, an object synchroniza-

tion policy).

4. Reply scheduling transparency. A client object should not have to wait for the server

object’s reply. It should be able to continue execution, receive other requests, and

invoke other objects in parallel. In this context, the client object must not force

the server object to cooperate in order to know when the reply to its request will

become available.

5. Composition of synchronization policies. It must be possible to reuse object synchro-

nization policies by composing exiting object synchronization policies.

The first three requirements allow server objects to be reused independently from

their clients. The fourth requirement allows the client and server objects to be reused

2.4. PROBLEMS 19

independently from each other. The fifth requirement forces the reuse of object syn-

chronization.

In addition to the emphasis on reusability, these five requirements also demand ex-

pressiveness. The second requirement demands the concurrent object policy. The third

requirement demands that object synchronization policies be able to use information

on the type of request and object state. The fourth requirement demands the possibility

of concurrency between client and server objects.

2.4 Problems

There are several techniques, tools and methods which integrate concurrency and

objects. They aim at satisfying the gathered set of requirements. Examples are object-

oriented analysis and design methods, object-oriented programming languages, and

class libraries. It can be verified, however, that the complete satisfaction of require-

ments raises problems concerning relationships between inheritance and synchroniza-

tion and between reusability and incremental development.

2.4.1 Inheritance and Synchronization

One of the features of object-oriented programming is code reuse through the in-

heritance mechanism. Nevertheless, when classes include synchronization code, reuse

through inheritance is not trivial. This problem is known as the inheritance anoma-

ly (Matsuoka & Yonezawa, 1993). The anomaly happens whenever local changes in

the inheritance hierarchy, e.g. adding a new method to a subclass, lead to changes in

synchronization constraints in another part of the hierarchy, e.g. changing synchro-

nization constraints of another previously defined method.

Kafura & Lee(1989) describe an inheritance anomaly scenario happening when a

programming language allows the definition of the set of operations which may occur

following each operation. This set is called enabled set and depends on the object’s s-

tate. For instance, class Buffer, with limited capacity, has at the end of each operation

20 CHAPTER 2. CONCURRENT OBJECT-ORIENTED PROGRAMMING

the code shown in figure 2.1.

if (items == 0) then accept {put}elseif (items < size) then accept {put, get}elseif (items == size) then accept {get};

Figure 2.1: Synchronization example: synchronization with enabled sets.

The inheritance anomaly problem appears when a new operation is defined in a

subclass, for it is necessary to redefine all superclass operations to include the new

operation in the enabled sets. Hence, superclass operations are not trivially reused.

Matsuoka & Yonezawa(1993) identify three kinds of scenario in which the inheri-

tance anomaly problem can occur: partitioning of states, history sensitiveness, and compo-

sition of synchronization code.

� Partitioning of states. To solve the enabled sets problem, abstract states which are

implementation independent (Kafura & Lee, 1989; Tomlinson & Singh, 1989) are

introduced.

empty={put}, partial={put,get}, full={get}

if (items == 0) then become emptyelseif (items < size) then become partialelseif (items == size) then become full;

Figure 2.2: Synchronization example: synchronization with abstract states.

Synchronization code now uses abstract states (see figure 2.2). Dependencies

between abstract states and operation identification are confined to the first line

of code in figure 2.2.

This solution solves the problem stated above. It is enough to add a new oper-

ation to the definition of the abstract states, and it is unnecessary to redefine all

operations. Nevertheless, it does not solve the problem when a new get2 op-

eration, which removes two items from the Buffer, is added. It is necessary to

split the partial abstract state into two other states and redefine all operations

to change the become instructions. In this case a partitioning of states scenario

occurs.

2.4. PROBLEMS 21

� History sensitiveness. To solve the problem of partitioning of states, a program-

ming language with guards has been proposed in which an operation is only

executed if its associated synchronization condition (guard) is true. A guarded

solution is presented in figure 2.3.

void put() when (items < size) { ... }void get() when (items > 0) { ... }

Figure 2.3: Synchronization example: synchronization with guards.

With this language the problem of partitioning of states does not occur. It is e-

nough to define a guard (items > 1) for the new get2 operation. Nevertheless,

guards are history-sensitive. For instance, operation gget, which is only allowed

to execute if the previously executed operation was not a put operation, leads to

the redefinition of all operations to update a new boolean synchronization vari-

able, after put, which becomes true after a put operation and false otherwise.

� Composition of synchronization code. Figure 2.4 presents a guarded solution for

class Lock. Class Lock has two operations: lock and unlock. To be able to

execute unlock the object must be in a locked state. Similarly, to be able to

execute lock the object must be in a !locked state.

Class Lock: {bool locked;

public:void Lock() {locked = False; }void lock() when (!locked) { locked = True; }void unlock() when (locked) { locked = False; }

}

Class L_Buffer: Buffer, Lock {public:

void L_Buffer();void put() when (!locked && (items < size)) { ... }void get() when (!locked && (items > 0)) { ... }

}

Figure 2.4: Synchronization example: composition of synchronization code.

The composition of Lock and Buffer, represented by class L Buffer in fig-

ure 2.4, must redefine all Buffer operations to test the value of the locked syn-

chronization variable. That is, the synchronization code composition problem

occurs.

22 CHAPTER 2. CONCURRENT OBJECT-ORIENTED PROGRAMMING

To solve the conflict between inheritance and synchronization, synchronization

should by reused and extended independently from functionality reuse.

2.4.2 Reusability and Incremental Development

The complexity inherent to concurrent programming suggests that object function-

ality should be coded first and that concurrency should be incrementally introduced

afterwards. For that, is it necessary that concurrency can be added without changing

functionality code, in order to control error detection and correction.

There is, however, a problem in this approach. Incremental development conflicts

with reusability, for the introduction of concurrency may lead to changes in object in-

terfaces. That is, is may not be possible to add concurrency simply by changing the

implementation of the objects supporting the program’s functionality. In these cases

the problem’s specification is said to be intrinsically concurrent. Thus, concurrency

introduction may not be transparent for client objects, forcing them to be recoded. As

an example, consider two objects supporting a program’s functionality and communi-

cating through procedure calls. To introduce concurrency between these two objects

it is necessary to change their interaction, i.e., it is necessary to change their interfaces

to support futures. It is also necessary to change each object’s implementation so they

may be able to synchronize themselves using futures. It should be noted that some

languages allow futures to be transparent but, in that case, they deny to client objects

the possibility of explicitly evaluating if the invocation has finished.

A buffer object’s synchronization is another example in which the sequential and

concurrent versions have different specifications. In the sequential version, operations

get and put return an error if the buffer object is, respectively, empty or full. In the

concurrent version, these operations are delayed until they are able to execute.

To solve this conflict, the incremental development process should manage com-

plexity also in the context of intrinsically concurrent programs.

2.5. RELATED WORK 23

2.5 Related Work

None of the concurrent object-oriented programming approaches completely

solves the problems stated above. Some approaches propose solutions to some of the

problems, with special relevance for the inheritance anomaly problem. However, these

proposals do not satisfy all the stated requirements.

In this section, related work is discussed by relating several proposals for each of

the aforementioned requirements. The aim is at situating the problems in their research

contexts. The proposed solutions are not exhaustively listed, however. For each prob-

lem, a complete related work analysis will be carried out as this dissertation’s work is

being described.

2.5.1 Expressiveness and Simplicity

Fulfillment of the expressiveness requirement must consider two aspects: the ex-

pressiveness of object concurrency, synchronization, and interaction constructs; and

the expressiveness of combinations of these constructs. That is, each construct must

have high expressive power and constructs must compose maintaining their expres-

siveness.

Object synchronization policies need specific information. For instance, produc-

er/consumer policies need to know the object’s state, and readers/writers policies

need to know about pending and executing invocations on an object. Thus, the ability

to support various types of information is a criterion for evaluating the expressiveness

of object synchronization constructs. Bloom(1979) enumerates six types of specific in-

formation needed by a vast number of policies:

1. type of invocation, for instance, the distinction between read and write opera-

tions in readers/writers policies.

2. order of invocation, for instance, to ensure that writes are performed by the same

order they are requested.

24 CHAPTER 2. CONCURRENT OBJECT-ORIENTED PROGRAMMING

3. invocation arguments, for instance, to ensure that, in print requests, small jobs

are processed first.

4. status of pending and executing invocations, for instance, in readers/writers

policies execution of write operations is delayed if there is still at least another

executing (read or write) invocation.

5. object state, for instance, in producer/consumer policies a production operation

only occurs if the buffer is not full.

6. invocation history, for instance, operation a cannot be executed if operation b

was executed immediately before.

Several constructs proposed for object synchronization do not easily support these

six types of information. For instance, DRAGOON (Atkinson et al., 1991) and POOL-

T (America, 1987) do not support invocation argument information, and ABCL/1 (Y-

onezawa et al., 1987) does not support object state information.

Many of the proposed constructs do not support different object concurrency poli-

cies. For instance, in both ABCL/1 (Yonezawa et al., 1987) and POOL-T (Ameri-

ca, 1987) all objects are sequential. In contrast, in Eiffel//, in the work by Karaor-

man & Bruno(1993), and in ABC++ (Arjormandi et al., 1995) all objects supporting syn-

chronization must be sequential. This means that there is, in the first case, an expres-

siveness limitation and, in the second case, a limitation on the possible combinations

of object concurrency and object synchronization.

There are approaches which only consider a form of object interaction. For in-

stance, the CSP language only supports synchronous one-way message passing, while

the POOL-T language only supports request/reply interactions in which an object

waits until receiving a reply. In addition, some approaches do not separate interac-

tions associated with the communication between concurrent objects from interactions

associated with the communication between objects in different address spaces. For

instance, the library proposed by Karaorman & Bruno only supports activity creating

in the case of remote invocations. The problem we find in these approaches results

2.5. RELATED WORK 25

from the lack of separation between concurrency and distribution, and the consequen-

t penalty to incremental development, for it is not possible to develop a concurrent

version without considering distribution.

The homogeneous model for integrating concurrent and object-oriented program-

ming, as proposed by Papathomas(1995), restricts expressiveness, for it forces all ob-

jects to be active. The homogeneous model, in addition to being potentially inefficient,

as all objects have control over concurrent invocations, imposes a limitation on pro-

gram design: the programmer cannot use passive objects whenever deemed necessary.

The combination of request/reply interactions and sequential objects is also con-

sidered inadequate by Papathomas(1995)5, for it constitutes a limitation on a program’s

concurrency since the client and server objects do not execute concurrently. However,

this limitation is real only if all program objects use this combination. In the context of

a more heterogeneous model, the combination may be useful if, for instance, concur-

rency between sequential clients and servers is not a goal.

It can be concluded that the aforementioned proposals for integrating concurrency

and objects present expressiveness limitations in terms of object concurrency, synchro-

nization, and interaction, and their respective combinations.

2.5.2 Reusability

Invocation synchronization based on unconditional acceptance does not satisfy the

reusability requirement. Unconditional acceptance may cause synchronization to be-

come the responsibility of either the client objects or the server object. In both cases,

basic synchronization primitives, such as semaphores, must be used. In the first case,

the server object cannot be reused independently from its client objects, for these are

responsible for its synchronization. In the second case, synchronization code becomes

tangled with functionality code preventing independent reuse.

Several solutions have been proposed to solve the inheritance anomaly problem.

In particular, proposals based on enabled sets, described above, cause redefinition of

5Liskov et al.(1986) also present an in-depth analysis of this combination.

26 CHAPTER 2. CONCURRENT OBJECT-ORIENTED PROGRAMMING

all code, for they do not separate synchronization code from functionality code.

Approaches such as Guide (Decouchant et al., 1991) and Eiffel// separate synchro-

nization from functionality, but localize both descriptions within the same class. These

approaches have the inconvenient of associating synchronization with a specific class,

thus preventing reuse of that synchronization by other classes.

DRAGOON separates synchronization and functionality descriptions, respectively

behavior and functionality classes. Behavior classes are later combined with function-

ality classes through a mechanism different from inheritance. In this way, synchroniza-

tion is generic, for it can be applied to different classes. In addition, separate reuse is

achieved through the separation of functionality and synchronization. Nevertheless,

the low expressive power of the DRAGOON language, which is used to define behav-

ior classes, causes the functional part to be used to support some synchronization poli-

cies. For instance, DRAGOON does not support information on invocation arguments.

Thus, it has to mix synchronization and functionality code to support that information:

separate reuse is lost. Thus, the inheritance anomaly problems again emerge.

McHale(1994) shows that the so-called inheritance anomaly does not result from

a semantic conflict between synchronization and inheritance, as claimed, for instance,

by Matsuoka & Yonezawa, but rather from the use of inheritance for two different

purposes: functionality reuse and synchronization reuse. Concluding, McHale affirms

that this problem is not synchronization-specific and that it will appear in other con-

texts where inheritance is used to reuse different kinds of code using a single class

hierarchy. In particular, Aksit et al.(1994b) have identified inheritance anomaly prob-

lems between functionality inheritance and inheritance of real-time specifications.

Another situation of inheritance anomaly appears when a single class hierar-

chy is used to reuse functionality and object concurrency, as described by Arjoman-

di et al.(1995). Suppose that an implementation of a sequential object, containing an

internal activity, is desired. In order to encapsulate the internal activity, it must be cre-

ated at object-creation time and must, repeatedly, execute a body. If this body is coded

in the class’ constructor, then the constructor must have an infinite cycle and the class

is unfit for reuse through inheritance as a way to add new functionality. In contrast, if

2.5. RELATED WORK 27

the body is defined as an operation, for instance main, then when adding functional-

ity, through inheritance and extension of operation main, a problem of premature in-

vocation of the redefined operation main appears. Operation main may not have the

necessary context, for the superclass constructor is executed before the new subclass’

constructor. Once again, this is a case of non-separation between object concurrency

and functionality, resulting from reusability limitations imposed by inheritance.

It can be concluded that, in the existing approaches, when integrating concurrency

and objects, reusability limitations appear due to the lack of separation between object

functionality, concurrency, synchronization, and interaction. These limitations may

also be due to the low expressive power of the support constructs.

2.5.3 Incremental Development

Object-oriented analysis and design methods (Hutt, 1994a; Hutt, 1994b) propose

development processes in which emphasis is put on incremental program construc-

tion. Incremental development has two aspects: vertical, in which a program’s

construction is done through functionality increments; and horizontal, in which

a program’s construction is done through non-functional increments, for instance

through addition of concurrency or distribution. However, these methods, of which

OMT (Rumbaugh et al., 1991), OOSE (Jacobson, 1992) and Booch (Booch, 1994) are ex-

amples,6 provide an in-depth treatment of incremental construction of analysis mod-

els, e.g. the use of Objectcharts (Coleman et al., 1992) for incremental introduction of

concurrency at the level of analysis models. However, they reduce the transition from

analysis to design to a set of guidelines, thus creating a gap between analysis and de-

sign models with negative consequences for incremental development.

Other methods, such as OOA (Shlaer & J.Mellor, 1992) and ROOM (Selic et al.,

1994), propose automatic generation of programs from analysis models. In this way,

the incremental development achieved during the analysis phase is applicable to the

whole of the development process. Nevertheless, this approach is still far from being

6The UML method (Booch et al., 1998), which aggregates OMT, OOSE, and Booch, does not havesignificant differences concerning concurrency.

28 CHAPTER 2. CONCURRENT OBJECT-ORIENTED PROGRAMMING

able to generate efficient programs and has been applied when models at the prob-

lem space level have a one-to-one correspondence with models at the solution space

level. This is the case of real-time programs (Selic et al., 1994) in which objects, and

corresponding state machines, perceived and described during analysis have a direct

correspondence with the physical devices executing the program. It should be noted

that the ROOM method allows incremental testing and debugging of analysis models

of concurrent programs in non-concurrent environments.

Recent proposals for enriching methods with notations for concurrency and syn-

chronization specification either still evidence gaps, e.g. MOOSE (Low et al., 1996; Ras-

mussen et al., 1996b; Rasmussen et al., 1996a), or use a high level language to execute

analysis models, e.g. Bergmans(1994).

Two approaches which do not evidence gaps between analysis and implementa-

tion, for they introduce object concurrency, synchronization, and interaction construct-

s at the programming language abstraction level, are described by Caromel(1993) and

Karaorman & Bruno(1993). Caromel describes a process, in the context of the Eiffel//

language, in which a sequential program is developed first and in later phases enriched

with object concurrency and synchronization. In the proposed process, enrichment of

a functional class is a transparent action, for the compiler automatically changes re-

turn values to futures. However, transparency may lead to inefficiency situations, for

a client class cannot take advantage of concurrently executing with the server class.

Karaorman & Bruno propose another development process in which a sequential ver-

sion of the program is also initially implemented, but clients of concurrency enriched

classes must be changed so they can use an asynchronous interface.

It can be concluded that few approaches support incremental development and

that approaches able to manage the complexity associated with incremental develop-

ment of inherently concurrent programs do not exist. It is, thus, necessary to find a

tradeoff solution between incremental development and reusability.

2.6. CONCLUSION 29

2.6 Conclusion

This chapter presents an analysis of the proposals for integrating concurrent and

object-oriented programming following the analysis done by Papathomas & Nier-

strasz.

An integration must satisfy three requirements:

� Expressiveness of concurrency support constructs and of their possible combina-

tions. Simplicity in using those constructs in a concurrent object-oriented pro-

gram.

� Separate reuse of concurrency support constructs and possibility of extending

them independently from functionality.

� Horizontal incremental development through the enrichment of sequential pro-

grams with object concurrency, synchronization, and interaction.

However, an integration of concurrency and objects which satisfies these three re-

quirements raises two problems:

� Inheritance and synchronization present interdependencies which cause a limitation

of the capability for separately reusing object functionality and synchronization.

Moreover, this interdependency is also applicable to object concurrency.

� Reusability and incremental development are incompatible if the introduction of con-

currency in a sequential program leads to the change of object interfaces.

None of the existing approaches for concurrent object-oriented programming sat-

isfactorily solves the problems stated. Some approaches propose solutions for some

of the problems. Particularly relevant are those to the inheritance anomaly problem.

However, there is none which satisfies all of the stated requirements

The next chapter presents the approach proposed in this dissertation. This ap-

proach integrates concurrency and objects satisfying the stated requirements and solv-

ing the problems raised by their complete fulfillment.

30 CHAPTER 2. CONCURRENT OBJECT-ORIENTED PROGRAMMING

3Separation and

Composition of Concerns

In this chapter an approach based on separation and composition of concerns is p-

resented. The approach integrates concurrent and object-oriented programming. Here,

several concurrent programming non-functional concerns are identified and construct-

s capable of expressing their policies are described. The way constructs are combined

and integrated in an incremental development process of concurrent programs is also

defined.

3.1 Basic Concepts

The proposed approach is built upon the following basic concepts: design pattern,

pattern language, and object-oriented framework.

3.1.1 Design Patterns

Experience using the object-oriented paradigm in program development has

shown that the basic construction unit is not the object itself, but small combinations of

objects with patterns for both structure and collaborations (Gamma et al., 1994; Pfister

& Szyperski, 1996).

A design pattern with objects is defined by Gamma et al.(1994) as: “The description

of a recurrent structure of communicating components that constitute a solution to a generic

design problem in a particular context.”

31

32 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

This definition highlights some of the fundamental features of design patterns: de-

scription, for the pattern is a description and not a program component; problem, for the

pattern describes not only the solution, but also the problem; context, for the pattern

occurs in a particular context; solution, for the pattern describes a structure of commu-

nicating components forming the solution; reuse, for the solution occurs recurrently;

generality, for it constitutes a solution for a general problem.

Two other features are:

� Abstraction. The pattern’s application does not have to be carried out always in

the same way. Thus, the description must have a higher abstraction level than

its concrete uses. That is, a design pattern is a description of a higher abstraction

level than code descriptions.

� Forces. The problem occurs in a context where several tradeoffs exist. These trade-

offs are called forces and they constrain the solution. The design pattern’s solu-

tion must balance the set of forces. This balance is called forces resolution.

The concept of a design pattern for describing object combinations with the afore-

mentioned properties was initially proposed by Beck & Cunningham(1987). A cat-

alogue with 23 design patterns was later presented (Gamma et al., 1993; Gamma

et al., 1994). Other notable references, including pattern catalogues, are the book by

Buschmann et al.(1996) and the PLoPD pattern collections (Coplien & Schmidt, 1995;

Vlissides et al., 1996; Martin et al., 1997).

Given the emphasis put on description, several formats have been proposed to

describe design patterns. One of the more broadly used is the format proposed by

Gamma et al.(1994):

� Name - the name identifying the pattern.

� Intent - a summary of what does the design pattern do.

� Also Known As - alternative names for the pattern.

3.1. BASIC CONCEPTS 33

� Motivation - a scenario illustrating a known design problem, as well as a concrete object

structure solving the problem.

� Applicability - when to apply the pattern.

� Structure - a diagrammatic representation of the objects and classes the pattern consists

of.

� Participants - classes and objects present in the pattern and their responsibilities.

� Collaborations - how the participants collaborate to carry out their responsibilities.

� Consequences - tradeoffs and results of using the pattern.

� Implementation - suggestions and techniques on how to implement the pattern.

� Sample Code - code fragments to illustrate the implementation using different program-

ming languages.

� Know Uses - examples of systems where the pattern has been applied.

� Related Patterns - other patterns having a similar intent or that may be applied in com-

bination with this pattern.

As an example, the Proxy pattern (Gamma et al., 1994) is succinctly described, using

part of the above format, in the following way:

� Name. Proxy.

� Intent. To provide a proxy of an object to control its accesses.

� Also Known As. Surrogate.

� Motivation. Controlling accesses to an object may be useful when it is desired to delay

its creation and initialization. As an example, consider a document editor capable of

including graphical objects inside a document. Some of the graphical objects may be

expensive to create, but opening a document should be a quick operation. It should be

noted that many of these graphical objects need not be immediately created for they may

be invisible when the document is opened. Thus, creation of the graphical objects may

be delayed in order to speed up opening the document.

34 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

But, how to delay creation of graphical objects without changing the document editor’s

code?

The solution is to replace each graphical object with its proxy, which the document editor

takes for the original object. The proxy implements the graphical object’s interface so

that it is only created when in fact necessary. That is, only when an operation requires

the graphical object’s data is it actually created by the proxy.

� Applicability. The Proxy pattern is applicable whenever the need exists for a more so-

phisticated and versatile object reference than a simple pointer. Several scenarios exist

where the Proxy pattern may be applied:

– A Remote Proxy is a local representation of an object in another address space.

– A Virtual Proxy creates expensive objects on demand.

– A Protection Proxy controls accesses to an object in order to grant different access

privileges.

– A Smart Reference replaces a pointer so that additional actions can be taken when

an object is accessed. For instance, it may count the number of references to an

object or load an object from persistent memory when it is accessed.

� Structure. The UML class diagram (Booch et al., 1998) shown in figure 3.1 illustrates the

class structure of the Proxy pattern.

Request()

Request()

Subject

Proxy

Request()

RealSubject realSubject

realSubject->Request()...

...

Client

Figure 3.1: The Proxy Pattern’s Structure

� Participants. The participants in the Proxy pattern are:

3.1. BASIC CONCEPTS 35

– Client. Requests services to Subject.

– Proxy. Contains the reference to access the RealSubject. Provides an interface

identical to the Subject’s so that it can replace RealSubject. Controls accesses

to RealSubject and may be responsible for creating and destroying it.

– Subject. Defines an interface common to RealSubject and Proxy.

– RealSubject. Defines the actual object represented by Proxy.

� Collaborations. The Proxy redirects invocations to RealSubjectwhenever necessary.

� Consequences. The Proxy pattern introduces an indirection when accessing an object. In

the Remote Proxy’s case, this indirection hides the fact that the object resides in another

address space. In the Virtual Proxy’s case, the indirection makes optimizations such as

creating the object only when necessary. In the cases of the Protection Proxy and Smart

Reference, additional actions are allowed whenever the object is accessed.

� Implementation. The Proxy pattern may take advantage of features of programming

languages. In C++ it may be implemented by redefining the -> access operator.

The format used by Gamma et al.(1994) has been, however, criticized for not mak-

ing explicit some pattern description aspects such as context, problem, and forces. For

instance, in the Proxy pattern, the context is described in the Applicability item; the

problem is described in the Motivation item for a particular case; and the forces are

not described at all. Aarsten (1997) uses a format in which these aspects are explicitly

handled.

The advantages of using design patterns are:

� They help manage complexity in program development for they describe ele-

ments with a granularity higher than object or class. They provide a predefined

implementation schema, describing their parts, collaborations, and responsibili-

ties.

� They provide common vocabulary and knowledge which, when shared by a pro-

gram development team, facilitates communication and document program ar-

chitecture.

36 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

� They stimulate knowledge reuse due to their abstraction level, thus allowing

their application in various ways.

3.1.2 Pattern Language

The reason for the pattern name comes from analogies found with the work of archi-

tect Christopher Alexander (1977; 1979) who proposed that the construction of build-

ings were based on reusing a set of patterns. For Alexander, a pattern is an element

from a pattern language, which forms a structured pattern collection. A pattern lan-

guage is more than a pattern collection or catalogue, though. It explains how patterns

are applied to a more general problem than the one solved by a single pattern.

In a similar way, design patterns describe solutions for design problems, but they

do not define how they should be applied in the more general context of the develop-

ment process. Thus, from an object-oriented programming perspective, the concept of

pattern language as defining a set of activities for program construction is also intro-

duced. These activities integrate design patterns in a program generation process.

The pattern language is composed by two kinds of pattern: process patterns and

design patterns. Process patterns describe activities defining when, and how, design

patterns should be applied for constructing the program.

Meszaros & Doble(1997) propose a format for pattern language description. In par-

ticular, they suggest that the general problem, context and forces the language aims at

solving be initially described. The problem, context and forces are common to all pro-

cess patterns. In addition, it is also suggested that an example be defined to illustrate

the pattern language’s usage.

Coplien(1995) describes a pattern language whose process patterns use a format

including the following items: Name, Problem, Context, Forces, Solution, and Result-

ing Context. In particular, the Resulting Context describes the result of applying the

pattern to the initial Context. The relation between Context and Resulting Context sets

a causality relation between process patterns which describes the program’s construc-

tion. As an example, a variation of the prototype process pattern, part of this pattern

3.1. BASIC CONCEPTS 37

language, is presented:

� Name. Prototype.

� Problem. User requirements are hard to validate.

� Context. It is necessary to gather requirements in the context of program development.

� Forces. Requirements are always changing. Requirements are usually too ambiguous. It

is desirable that requirements changes occur early in the development process.

� Solution. To build a prototype to help understand and validate requirements. Prototypes

are very useful in the validation of external interfaces.

� Resulting Context. A better assessment of requirements through the use of a prototype

as a communication tool with the users.

3.1.3 Object-oriented Framework

An object-oriented framework consists of a group of classes defining an abstrac-

t design to solve a family of problems (Johnson & Foote, 1988). An object-oriented

framework defines a skeleton which must be fleshed out to support the specific needs

of each program (Wirfs-Brock et al., 1990).

Through the use of object-oriented frameworks programmers reuse the frame-

work’s architecture, including its collaborations, having only to specialize some of

the classes with information specific to the problem being solved. The framework’s

customization is usually defined by adding methods to subclasses of the framework’s

classes. These methods must know the internal structure and behavior of their respec-

tive super-classes. This is called white-box reuse, for the programmer has to know the

object-oriented framework’s internal structure to be able to use it.

The object-oriented framework can also be customized through a set of predefined

components containing customizations. In this way, to be able to reuse the framework,

a programmer has to have knowledge only of these components’ interface. This is

38 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

black-box reuse: the use of object-oriented frameworks allowing black-box reuse facil-

itates learning but reduces flexibility. That is, by offering predefined customizations,

components reduce the set of possible customizations.

A design pattern is different from an object-oriented framework, in spite of both

defining an abstract design:

� Object-oriented frameworks are defined by their code, while design patterns ab-

stract several implementations.

� Object-oriented frameworks describe architectures with greater granularity than

design patterns. In particular, an object-oriented framework may contain the

implementation of several design patterns.

It is important to note that design patterns can be used for documenting object-

oriented frameworks (Johnson, 1992), as these usually consist of several design pat-

terns. In particular, Gamma et al.(1994) have identified design patterns by analyzing

several object-oriented frameworks, such as ET++ (Weinand et al., 1988), MVC (Kras-

ner & Pope, 1988), and Unidraw (Vlissides, 1995).

3.2 Separation and Composition of Concerns

In this section the approach proposed in this dissertation is introduced. The ap-

proach integrates concurrent and object-oriented programming and is based on sepa-

rately handling non-functional concerns of concurrent programming and their compo-

sition.

The proposed approach consists of the following elements:

� Concern. Each concern identifies a concurrency aspect for which it is possible to

define a construct. Constructs for each concern must be orthogonal to each other.

� Design Pattern. Each concern’s constructs are defined as design patterns describ-

ing the solution’s collaborations structure.

3.2. SEPARATION AND COMPOSITION OF CONCERNS 39

� Pattern Composition. Design patterns are composed so that they express possi-

ble concern compositions. The result of each composition is called composition

pattern.

� Pattern Language. Design patterns must be incrementally applied so that they

enrich application functionality with concurrency. The strategy for introducing

design and composition patterns in a program is defined by a pattern language.

� Object-oriented Framework. An object-oriented framework implements design pat-

terns and their compositions. The framework has a three-layered architecture

which rules the implementation of both separation and composition of concerns.

As will be seen, the approach of separation and composition of concerns has a set of

properties which contributes to the satisfaction of the requirements and to the solution

to the problems mentioned in chapter 2.

3.2.1 Concerns

Three concerns are considered in this dissertation: object synchronization, object con-

currency, and object recovery. Concurrency concerns are applied to a “concurrency-free”

object, the functional object, whose interface defines the set of services it provides.

Object synchronization and object concurrency concerns handle the same aspects

than the concurrency constructs with the same name, described in section 2.2.3. The

interaction between objects is also included in the object concurrency concern, for it

is strongly related to inter-object concurrency. The object recovery concern appears

as a consequence of the object synchronization concern policies which allow finished

invocations to be aborted with the consequent need for recovering the object state prior

to the invocation. This is, for instance, the case of optimist object synchronization

policies.

The composition of these three concerns allows the definition of synchronized, con-

current, and recoverable objects, as well as some of their combinations.

40 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

Each concern can be handled in three levels of abstraction: model, policy, and

mechanism.

� Model. Models describe user expectations about program behavior in “non-

functional” terms. For instance, transparency is a model in which object synchro-

nization, concurrency, and recovery are not apparent to the user: the program

executes according to the semantics of sequential execution.

� Policy. Policies are algorithms supporting models. For instance, a pessimist syn-

chronization policy which serializes invocation execution supports the synchro-

nization concern’s transparency model. There may exist several policies support-

ing the same model.

� Mechanism. Mechanisms are used in policy implementation. For instance,

semaphores are synchronization mechanisms. It is worth distinguishing between

abstract and concrete mechanisms.1 The former are platform-independent while

the latter are platform-specific. Abstract mechanisms are usually supported by

class libraries implemented on top of various platforms: for instance, the ACE

library’s synchronization mechanisms (Schmidt, 1995). It should be noted that a

given mechanism can be used in the context of different concerns.

The focus of this dissertation is at the policy abstraction level. The mechanism

level is already supported by class libraries (Schmidt, 1995). In the context of this

dissertation, the model abstraction level is only relevant in the identification of non-

functional requirements of concurrent programs and in setting a correspondence to

the requirements of design classes. For instance, a non-functional requirement, such as

simultaneous execution of a client program and its print request, forces the association

of object concurrency policies with some of the program’s functional objects.

1Sometimes also referred to as, respectively, logic and physical mechanisms.

3.2. SEPARATION AND COMPOSITION OF CONCERNS 41

3.2.2 Design Patterns

In this approach a design pattern is defined for each concern. Design patterns must

have the following properties which, as will be seen, contribute to the satisfaction of

the integration requirements of concurrent and object-oriented programming as stated

in chapter 2:

� Expressiveness. Concern policies are supported by specializing the design pattern

associated with the concern. Thus, the expressiveness requirement of concurren-

cy constructs is achieved. For instance: an object concurrency pattern has, among

others, specializations for sequential and concurrent objects.

� Modularity. Each concern’s design pattern must separate the concern’s solution

from the object’s functionality. Modularity facilitates satisfaction of the incre-

mental development requirement, for it is possible to develop and replace the

implementation of the concern’s constructs separately from the object’s function-

ality.

� Encapsulation. Each concern’s constructs must be localized near the functional

object. They must not be spread out among its client objects. For instance, each

object must be responsible for its own synchronization, for the division of this

responsibility among its client objects may lead to deadlock situations. In this

way, the reusability requirement is guaranteed, for objects integrated with their

synchronization are reused independently from their clients.

� Reusability. Each concern’s constructs and functional objects must be separately

reusable and extendible. It should be noted that reusability presumes modular-

ity and the capability for incrementally extending constructs. That is, synchro-

nization and functionality must not be reused together using, for instance, in-

heritance. They should be associated, a posteriori, with each concrete class to be

synchronized.

In order to emphasize the properties design patterns must exhibit, the following

description format is used:

42 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

� Name - the design pattern’s name.

� Intent - a summary of what does the design pattern do.

� Problem - states the problem associated with the concern.

� Concern Analysis - a detailed analysis of the concern, of its problems, as well as of ex-

isting solutions. Identifies policies the pattern must support to fulfill the expressiveness

property.

� Forces - defines the properties the concern’s solution is required to have: expressiveness,

modularity, encapsulation, and reusability.

� Structure - a diagrammatic representation of the objects and classes the pattern consists

of. This representation uses UML class diagrams.

� Participants - classes and objects participating in the pattern and their responsibilities.

� Collaborations - the way participants collaborate in order to satisfy their responsibilities.

Includes diagrammatic collaboration representations through UML sequence diagrams.

� Forces Resolution - the way the design solution satisfies the previously stated forces:

expressiveness, modularity, encapsulation, and reusability.

In relation to the format by Gamma et al.(1994), here is given more emphasis to

the required properties and their satisfaction by design patterns. A concern analysis

is carried out to identify problems and solutions. Also, it should be noted that known

uses are not indicated. However, reusability is one of the required properties whose

satisfaction is shown in the forces resolution item through the features inherent to the

design pattern’s structure and collaborations.

The design pattern’s structure and collaborations are defined using the object-

oriented paradigm’s basic concepts: class, object, generalization (specialization), and

polymorphism. Since these concepts are implemented by object-oriented languages, it

is guaranteed that design patterns are independent from a particular object-oriented

programming language.

3.2. SEPARATION AND COMPOSITION OF CONCERNS 43

3.2.3 Pattern Composition

Through the orthogonality of constructs described by design patterns, concern

composition is obtained from the composition of each concern’s design patterns. For

instance, to obtain a synchronized and concurrent object it is necessary to compose

design patterns corresponding to the object synchronization and object concurrency

concerns.

The composition of design patterns also represents a design solution in which its

participants are built by composing each involved pattern’s participants. In addition,

the composition pattern’s collaborations are built from the collaborations of each pat-

tern participating in the composition.

The composition of design patterns must preserve the properties of each design

pattern isolated from each other. For instance, the composition of concurrent object

and synchronized object patterns must preserve the expressiveness each pattern alone

provides to the corresponding concern.

In spite of the orthogonality between concern constructs, it is necessary to integrate

their participants and respective collaborations in order to achieve a consistent compo-

sition. The consistency property must, thus, be guaranteed by pattern composition:

� Consistency. Design pattern’s concerns to be composed may not be completely or-

thogonal, existing, for instance, restrictions on possible participant combinations

and collaborations for each pattern. Thus, pattern composition must describe

which combinations are consistent.

Pattern composition is described using a format identical to the one used in design

pattern descriptions, but emphasizing composition aspects:

� Name - the composition pattern’s name.

� Intent - a summary of what does the composition pattern do.

� Problem - states the problem associated with the composition.

44 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

� Analysis - a detailed analysis of composition possibilities. Identifies the set of consistent

combinations.

� Forces - defines the properties required by the composition: expressiveness, modularity,

encapsulation, reusability, and consistency.

� Structure - a diagrammatic representation of the objects and classes the pattern consists

of. Some of these objects and classes result from composing objects and classes from

design patterns. The representation uses class diagrams enriched with a notation to

emphasize the design patterns each of the involved classes in the composition comes

from (Eriksson & Penker, 1998).

� Participants - classes and objects participating in the composition and their responsibil-

ities. Some participants aggregate the responsibilities of several design patterns’ partici-

pants.

� Collaborations - defines collaborations by combining design patterns’ collaborations.

These collaborations are represented as UML sequence diagrams.

� Forces Resolution - the way the previously stated forces are balanced by the composition

pattern: expressiveness, modularity, encapsulation, reusability, and consistency.

3.2.4 Pattern Language

The application of design patterns and of their compositions in an incremental de-

velopment process of concurrent programs is defined by a pattern language. The pat-

tern language describes the activities of an incremental development process in which

the introduction of concurrency is delayed in order to allow testing and debugging of

application functionality in a non-concurrent, thus deterministic, environment.

The pattern language consists of two process patterns defining two development

process activities:

� Functionality. This activity builds a program to implement the program’s func-

tionality. This program is tested and debugged in a deterministic environment.

3.2. SEPARATION AND COMPOSITION OF CONCERNS 45

� Concurrency. This activity enriches the program developed in the previous activ-

ity with concurrency concerns. These must be incrementally introduced delaying

the introduction of concerns responsible for non-determinism.

It should be noted that this pattern language is not aimed at defining a complete

development process. It aims at defining the main activities to support incremental

development of concurrent programs. The incremental development recommended

by the language deals with non-functional concerns (horizontal increments). However,

the language does not prevent development with vertical increments (functionality

increments) typical of object-oriented programming.

Process patterns are described in chapter 8 using a format similar to the one used

by Coplien(1995) and previously mentioned in section 3.1.2. However, item Solution is

replaced by item Strategy, to emphasize the fact that development process activities are

being described. In addition, item Example is introduced to illustrate process pattern

application in a concrete case of development of concurrent programs.

3.2.5 Three-layered Object-oriented Framework

Design and composition patterns are implemented in a three-layered object-

oriented framework with separation of concerns. In this framework, classes imple-

menting design and composition patterns are grouped within components. A com-

ponent is defined by Nierstrasz & Dami(1995) as being an abstraction of a software

module which encapsulates its implementation’s details and has an explicit interface

through which systems can be built by instantiating its parameters and connecting

to other components. In the object-oriented framework’s concrete case, components

consist of classes implementing design and composition patterns, and are instantiated

either through instantiation of the explicit interface’s parameters or through special-

ization of some of their classes.

Figure 3.2 represents a component diagram. It illustrates the architecture of the

three-layered object-oriented framework with separation of concerns.

The object-oriented framework’s three layers are:

46 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

CONCERN LAYER

COMPOSITION LAYER

APPLICATION LAYER

CONCERN B

COMPOSITION Y

PROGRAM

COMPOSITION X

CONCERN A

CLASS C1 CLASS C2CONCERNS A,B

compositionconcern

compositionconcern

compositionconcern

componentintegration

componentintegration

policy policy policy

CONCERN A

customization customization customization

Figure 3.2: Architecture of the Three-layered Object-oriented Framework with Separa-tion of Concerns.

� Concern. The concern layer contains classes implementing each of the design

patterns. These classes are grouped within components called concern compo-

nents. The framework contains three components for the object concurrency, ob-

ject synchronization, and object recovery concerns. In addition to ensuring the

design patterns’ properties, concern components must provide a set of classes to

support composition of concern components and customization of concern poli-

cies to be done, respectively, in the composition and application layers.

� Composition. The composition layer contains classes implementing composition

patterns. These classes are grouped within components called composition com-

ponents. In addition to ensuring the composition patterns’ properties, compo-

sition components must define a minimal interface. A composition component’s

minimal interface is instantiated to integrate the component in the application

layer. Using the minimal interface, the final programmer does not need to know

the details of the patterns’ composition, which are encapsulated by the compo-

nent, thus simplifying the framework’s use. The singular composition of concern

components, e.g. Composition X in figure 3.2, is needed to give the corre-

sponding concern component a minimal interface.

3.2. SEPARATION AND COMPOSITION OF CONCERNS 47

� Application. In the application layer composition components are integrated in

the final program and concern components are customized so that they provide

the policies required by the program’s functional objects. For instance, to obtain

a concurrent and synchronized object it is necessary to integrate the functional

object and the concurrent synchronized object composition component using it-

s minimal interface. In addition, it is necessary to customize the corresponding

concern components by specializing some of their classes. It should be noted that

the composition component must be independent from customizations of con-

cern components. Integration and customization in the application layer must

respect the following properties:

– Transparent Integration. The integration of composition components with

functional objects must be as transparent as possible, so that functional ob-

jects and their clients need not be changed. For instance, the Proxy pattern

may be applied to perform the transparent integration of composition com-

ponents in the program. In this way, the integration of composition com-

ponents is done through a new implementation of the functional object’s

interface. This new implementation integrates the composition componen-

t’s minimal interface with the functional object’s previous implementation.

Thus, the integration does not change the functional object’s implemen-

tation facilitating incremental development. Moreover, client need not be

changed for the interface they use remains the same.

– Incremental Customization. The customization of concern components must

be independent from the customizations of the remaining concern com-

ponents. For instance, incrementally changing a synchronized object into

a concurrent and synchronized object should require only, from the cus-

tomization point of view, the concurrency component’s customization. The

previous customization of the synchronization component is reused.

The object-oriented framework implements the property of pattern reusability ei-

ther as white-box reuse or as black-box reuse. Customization of concern component

classes is white-box reuse, which has great flexibility but requires the programmer

48 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

to know about the design pattern’s internal structure. However, if the programmer

uses predefined policy implementations then black-box reuse is being done for the

programmer has only to create instances of previously customized classes and asso-

ciate them with the corresponding invocations. In this situation, arrow policy cus-

tomization in figure 3.2 indicates, in fact, that a previously customized policy is

being used.

Design and composition patterns constitute a description of the object-oriented

framework. However, the object-oriented framework contains implementation deci-

sions that need to be documented, such as the use of template classes. Thus, class

diagrams, used to describe the patterns’ structure, must be rewritten to describe the

implementation’s specific features.

An object-oriented framework for concurrency was developed in C++ (Strous-

trup, 1991) using the abstract concurrency and synchronization mecha-

nisms provided by the ACE library. The framework is available from

http://www.esw.inesc.pt/˜ars/dasco/framework.html.

3.2.6 Results

The approach proposed for concurrent object-oriented programming meets the re-

quirements stated in chapter 2:

� Expressiveness and Simplicity. The expressiveness property of design patterns al-

lows them to support concern policies. Concern combination is expressed by

composition patterns and this composition is simple, for the separation between

concerns reduces the number of dependencies between them, thus simplifying

composition. It should be noted that, when concerns are not completely orthog-

onal, the consistency property of composition patterns guarantee their consisten-

t composition and the corresponding component’s minimal interface hides the

composition’s complexity from the final programmer.

� Reusability. The reusability requirement is achieved, for the modularity of design

patterns allows separate reuse of the concern’s construct and of the functional

3.2. SEPARATION AND COMPOSITION OF CONCERNS 49

object. In addition, the design pattern associated with each concern supports

incremental extension of the concern’s construct.

� Incremental Development. The separate definition of a design pattern for each con-

cern and its later composition forms the basis for incremental development. The

pattern language describes how design patterns should be applied in successive

increments of increasing complexity. The property of incremental customization

in the application layer of the object-oriented framework allows reuse of previous

customizations.

The problems associated with satisfaction of these requirements are handled by the

proposed approach as follows:

� Inheritance and Synchronization. The conflict between inheritance and synchro-

nization corresponds, in fact, to inheritance use for both ends, in this case, func-

tionality and synchronization reuse. That is, it will also emerge in the other con-

cerns. The modularity property of design patterns creates separated inheritance

hierarchies for functional classes and for classes of other concerns. This permits

conflict reduction, for inheritance hierarchies are separated and can be indepen-

dently extended.

� Reusability and Incremental Development. The conflict between reuse and incremen-

tal development is solved by the pattern language. In the functionality pattern

an object’s concurrent interface is supported, if necessary, by applying design

patterns associated with concerns. For instance, the object’s interface returns fu-

ture objects. However, to control complexity, these patterns are customized with

“non-concurrent” policies, which allow sequential execution. For instance, the

concurrent object pattern is applied but customized to use the invoking object’s

activity.

50 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

3.3 Related Work

Approaches for concurrent object-oriented programming have been classified in

terms of two features of their concurrency constructs:

� Constructs are defined using a language or are coded in a class library.

� Constructs are unified with the object concept or are separated from it being in-

tegrated only in the final program.

This section identifies, initially, approaches conforming to these two classifications.

Finally, some approaches based on separation of concerns are analyzed.

3.3.1 Languages or Class Libraries

Library-based approaches (Goldberg & Robson, 1983; Bershad et al., 1988; Briot,

1989; Karaorman & Bruno, 1993; Sousa et al., 1993; Arjormandi et al., 1995; Schmidt,

1995) consist of a set of classes which abstract and encapsulate concurrency constructs.

In this way, concurrency constructs are not part of the programming language itself.

Language-based approaches may define a new language (Agha, 1986; America,

1987; Nierstrasz, 1987; Yonezawa et al., 1987; Kafura & Lee, 1989; Tomlinson et al., 1989;

Atkinson et al., 1991; Decouchant et al., 1991; McHale et al., 1991; Baquero et al., 1995;

Lopes, 1997) or extend an existing one (Caromel, 1990a; Lohr, 1992). These program-

ming languages contain constructs, e.g. commands or keywords, to support concur-

rency.

Library-based approaches are more popular than language-based ones, for they

do not force the replacement of existing development environments, while language-

based approaches, to be useful, demand a set of auxiliary development tools for the

new language. However, library-based approaches do not allow static verification of

program correction such as, for instance, static type verification.

Some library-based approaches (Goldberg & Robson, 1983; Bershad et al., 1988;

Sousa et al., 1993; Schmidt, 1995) offer a set of classes which abstract and encapsulate

3.3. RELATED WORK 51

synchronization and concurrency primitives such as, for instance, semaphores. These

libraries’ main objective is to provide a set of platform-independent abstract mecha-

nisms.

The approach proposed in this dissertation is library-based. More precisely, it is

based on an object-oriented framework. This approach defines concurrency constructs

at the policy abstraction level as do, for instance, the approaches proposed by Karaor-

man & Bruno(1993) and Arjomandi et al.(1995), but in relation to which it has greater

expressiveness, as shown in section 2.5.1. The proposed approach uses a library of

abstract mechanisms (Schmidt, 1995) to implement policies.

3.3.2 Unification or Separation

Some approaches (Agha, 1986; America, 1987; Nierstrasz, 1987; Yonezawa et al.,

1987; Kafura & Lee, 1989; Tomlinson et al., 1989; Caromel, 1990a; Decouchant et al.,

1991; Lohr, 1992) unify concurrency constructs with the concept of object. These ap-

proaches integrate concurrency and objects in an object model. For instance, in the

POOL-T (America, 1987) language, all objects are sequential. The advantage of u-

nification approaches is in the simplicity they present to the final programmer, for

concurrency concerns are more transparent. For instance, in the POOL-T language,

when a programmer defines a new class, all its objects are automatically sequential.

The uniformity associated with the model corresponds to the homogeneous model

proposed by Papathomas & Nierstrasz(1991) with the expressiveness limitations dis-

cussed in section 2.5.1. Nevertheless, to be flexible, these approaches have to include in

the language composition and extensibility primitives (Frolund, 1992) associated with

concurrency constructs, which, sometimes, have unexpected repercussions on the se-

mantics of the object model. Perhaps for this, many of these unification approaches

only handle one concurrency concern: object synchronization.

To avoid the flexibility problems of unification approaches, approaches with sepa-

ration of concerns (Briot, 1989; Atkinson et al., 1991; Aksit et al., 1994a; Baquero et al.,

1995; Hursch & Lopes, 1995; McAffer, 1995; Aksit, 1996; Kicsales et al., 1997) integrate

concurrency constructs only in the final program. The gain is in flexibility, for con-

52 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

currency constructs are separated from functionality, thus facilitating their customiza-

tion and reuse. In contrast with unification approaches, which are language-based,

approaches with separation of concerns may be language-based (Atkinson et al., 1991;

Aksit et al., 1994a; Baquero et al., 1995; Kicsales et al., 1997) or library-based (Briot, 1989;

McAffer, 1995).

In addition, approaches with separation of concerns may be classified according

to the integration mechanism of concurrency constructs and functional objects. This

mechanism may be based on design solutions (Gamma et al., 1994), on compilers (Ba-

quero et al., 1995), or on reflection (Maes, 1987).

The Proxy pattern is an example of an integration mechanism based on design solu-

tions. When applying the Proxy pattern to the functional object, the interface is separat-

ed from the implementation. The integration of concern constructs is done through a

new implementation of the functional object’s interface which uses the previous func-

tionality implementation. Thus, the integration does not change the functional object’s

implementation, facilitating incremental development. Moreover, clients need not be

changed for the interface they use remains the same. The disadvantage of this solu-

tion is that all functional classes must have an abstract interface and objects creating

instances of these classes must use an Abstract Factory (Gamma et al., 1994) so that they

may ignore the actual class implementation they are using.

When using a compiler as an integration mechanism (Baquero et al., 1995), code

generation is automatic and avoids the need for functional classes to have abstract

interfaces. However, this integration mechanism does not allow run-time substitution

of concurrency support constructions.

Reflection (Maes, 1987) is an integration mechanism2 which allows control and cus-

tomization of a computational system’s behavior, for the system’s static and dynam-

ic features are represented as a concrete meta-system. The computational system’s

behavior is controlled and customized through changes to this meta-system. In the

context of the object-oriented paradigm, it is said that the meta-system is composed

2Briot et al.(1998) considers reflection as classifying a set of approaches. This classification is centeredon the properties of integration mechanisms.

3.3. RELATED WORK 53

by meta-objects, which are altered through a meta-interface, which, in turn, defines a

meta-object protocol (Kicsales et al., 1991). In the context of concurrency, meta-objects

support the program’s concurrency constructs, thus providing the separation between

the functional and concurrent parts. It is the responsibility of the reflection’s object

model to integrate the functional and concurrent parts. In addition, reflection allows

run-time meta-object replacement.

The approach proposed in this dissertation is based on separation of concerns and

uses design patterns to separately describe concurrency constructs. Implementation-

s of design patterns follow a three-layered architecture with separation of concerns.

The minimal interface property of the architecture’s composition components simpli-

fies their use by the programmer of functional classes, for it limits the set of concepts

the programmer must know and handle. The properties defined by the three-layered

architecture do not impose the use of a specific integration mechanism. In the contex-

t of this dissertation’s work, an object-oriented framework was implemented in C++

which uses the Proxy pattern as integration mechanism. Alone, this implementation

does not contemplate run-time replacements as those permitted by, for instance, re-

flection. However, run-time replacements require concern solutions to define stable

states in which a replacement can consistently occur. That is, run-time replacements

raise requirements on the definition of constructs associated with each concern and do

not depend only on the integration mechanism’s features3.

The separation of the concurrency concerns forces their later composition. Two per-

spectives exist regarding concern composition: orthogonal and non-orthogonal. The

orthogonal perspective considers concerns to be completely orthogonal being enough

to join solutions (Aksit et al., 1994a; Forman et al., 1994; McAffer, 1995), while the non-

orthogonal perspective considers that concern composition must consistently integrate

the concerns’ parts exhibiting semantic overlapping (Mulet et al., 1995; Kicsales et al.,

1997).

3Even in approaches using reflection as integration mechanism, we are not aware of any work inwhich this subject is handled with any degree of depth being the discussion limited to the choice ofpolicies at object initialization time. An in-depth discussion of dynamic policy replacement is done inthe area of dynamic configuration of distributed systems (Kramer & Magee, 1985; Rosa & Silva, 1998).

54 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

The approach proposed in this dissertation considers non-orthogonal concern com-

position: composition components are built by applying the composition mechanisms

of the object-oriented paradigm to the classes of concern components. This is also the

approach proposed by Mulet et al.(1995) in which specialization and aggregation are

used to compose meta-objects.

3.3.3 Approaches with Separation of Concerns

As seen in the previous section, there are several concrete proposals for languages

and libraries for separation and composition of concerns: aspect-oriented program-

ming (Kicsales et al., 1997), composition filters (Aksit et al., 1994a), CodA (McAffer,

1995), and Actalk (Briot, 1989). These approaches will be compared, in the following

chapters, with the approach proposed in this dissertation.

Aspect-oriented programming (Kicsales et al., 1997) consists of a component lan-

guage to program functionality, one or more aspect languages to program concerns,

and an aspect weaver which combines languages. Programs are separately built us-

ing the different languages. One component program and several aspect programs are

written, being the aspect weaver’s responsibility to combine them at compile- or run-

time. This proposal is language-based and has an integration mechanism, the aspect

weaver, which requires separation between functionality (component program) and

the other concerns (aspect programs). The problem of mixing different kinds of code,

referred to as code tangling, which is handled by aspect-oriented programming was

previously described by Hursch & Lopes(1995). Languages for the concerns of syn-

chronization and argument passing in remote invocations were later defined (Lopes

& Kiczales, 1997; Lopes, 1997). Aspect-oriented programming allows non-orthogonal

composition and delegates on the aspect weaver the resolution of complexity associat-

ed with concern combination. In spite of being interesting, sufficient examples do not

yet exist which demonstrate that non-orthogonal compositions can be handled auto-

matically and with some generality. For instance, the aspects composed by Lopes(1997)

are completely orthogonal and thus simple to compose. This approach still presents

the problem of language-based approaches: it forces the programmer to use new lan-

3.3. RELATED WORK 55

guages and development tools.

Composition filters (Aksit et al., 1994a), an approach claiming to be aspect-

oriented (Aksit, 1997), extend the object model with composition filters. Each object

possesses various non-functional components, called composition filters, which inter-

cept object messages, both incoming and outgoing, expressing restrictions such as, for

instance, on synchronization. There are several kinds of filter, each representing an

aspect. Their specification is done using an aspect language. Filters are composed

sequentially by the aspect weaver. Composition semantics is given by the logical oper-

ators: AND, if a message must go through both filters; and OR, if a message needs to go

only through one of them. This approach is language-based and, given its composition

features, presumes aspects to be completely orthogonal. Composition filters share the

problems of language-based approaches. Their orthogonality prevents the existence of

variations in concern composition.

CodA (McAffer, 1995) is a reflexive meta-object architecture. There are, by default,

seven meta-objects: send, accept, queue, receive, protocol, execution, and

state. For instance, to define a sequential object it is enough to define a specialization

of queue which places messages in a buffer, and specialize execution to generate

an activity which will run forever executing the buffered messages using meta-object

receive. Due to the fine granularity of each meta-object, these have a small number

of responsibilities and their composition is orthogonal, for it is sufficient to specialize

each of them separately. The disadvantage of CodA is in the complexity associated

with meta-object composition, for they do not have a correspondence with concerns

and thus it is necessary to understand all roles a meta-object has in different concerns.

In contrast, the approach proposed in this dissertation defines components which ag-

gregate classes belonging to a concern’s solution. It is easier to define each concern’s

customization, for it is separated from composition, and the composition component

encapsulates the complexity associated with the composition of concern components.

The article on CodA does not provide many object synchronization and object concur-

rency examples; it is, thus, difficult to perform an in-depth evaluation of this approach

from the point of view of expressiveness.

56 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

Actalk (Briot, 1989) is an reflexive object-oriented framework for concurrency writ-

ten in Smalltalk. It allows customization of various concurrency and synchroniza-

tion policies (Briot, 1996). Actalk was designed with the objective of being uniform,

modular, minimal, extensible, and offering an integrated development environmen-

t. The Actalk object-oriented framework defines three components: behavior, activi-

ty/synchronization, and communication. Functionality is contained within the behav-

ior component. The activity/synchronization component has an internal activity and

is responsible for synchronization. The communication component is responsible for

defining the various communication types. Actalk’s architecture does not separate con-

cern customization from concern composition, i.e., it does not follow the three-layered

architecture and, thus, has problems combining different customizations of the same

component.

3.4 Conclusion

This dissertation proposes an approach for the development of concurrent object-

oriented programs based on design and composition patterns, on a pattern language,

and on an object-oriented framework.

In order to control the complexity associated with the development of concurrent

programs different abstraction levels have been defined. Each corresponds to a differ-

ent kind of user/programmer:

� The final programmer may use the object-oriented framework knowing only the

policy, for instance, readers/writers, needed for the functional object. In this case,

the programmer uses a predefined policy of the object synchronization pattern. If

the programmer wants to customize the policy according to specific needs, then a

specific synchronization policy has to be implemented. For this, the programmer

must possess the knowledge described by the object synchronization pattern and

know how it is implemented in the corresponding concern component. In this

situation, the programmer is not required to know about the particularities of

composition patterns nor about their implementation.

3.4. CONCLUSION 57

� Framework programmers need to have more knowledge, both of specific do-

mains: object synchronization, object concurrency, and object recovery; and of

the patterns’ implementation and their composition.

This dissertation proposes an approach for integrating concurrent and object-

oriented programming. The approach contains the following contributions:

� Solution for the object synchronization, object concurrency and object recovery

concerns, described as design patterns. These patterns have the properties of ex-

pressiveness, modularity, encapsulation, and reusability. These properties allow

the approach to be characterized as being of the separation of concerns category.

� Solutions for the consistent combination of design patterns associated with the

three concurrency concerns, described as composition patterns. Composition

patterns have the consistency property that guarantees non-orthogonal composi-

tion of design patterns associated with concerns.

� Solution for an incremental development of concurrent programs controlling

complexity, described as a pattern language. The pattern language defines activ-

ities which integrate design and composition patterns in a development process

in which non-determinism associated with concurrency may be introduced in the

final stages.

� Implementation of design and composition patterns as a three-layered object-

oriented framework with separation of concerns. The framework facilitates the

use of composition components by the programmer through the definition of a

minimal interface and allows the existence of predefined solutions for different

concern policies.

The proposed approach has generic features that allow its use in contexts other

than concurrency. This approach has also been used in distributed systems partition-

ing (Silva et al., 1996b; Goncalves & Silva, 1997; Rosa & Silva, 1997; Silva et al., 1997a;

Rosa & Silva, 1998; Silva et al., 1998).

This dissertation’s contributions in terms of an approach definition are:

58 CHAPTER 3. SEPARATION AND COMPOSITION OF CONCERNS

� Defines three abstraction levels: model, policy, and mechanism. These levels

provide the context for an incremental development process.

� Solutions are described as design and composition patterns using only the object-

oriented paradigm’s base concepts, independently from any programming lan-

guage. Thus, these descriptions document any implementation.

� Definition of a reference architecture for implementing separation and compo-

sition of concerns. This architecture defines properties any implementation of

design and composition patterns must possess. The architecture is independent

from the integration mechanism to be used.

These contributions have been presented in international conferences and can be

found in their proceedings. Some of them were published in journals or as book chap-

ters:

� Silva et al.(1995) presents the DASCo approach (Development of Distributed Ap-

plications with Separation of Concerns) for developing concurrent and distributed

programs. In this article emphasis is put on separation and composition of con-

cerns as well as on abstraction levels.

� Silva et al.(1996d) and Silva(1997a) present the Synchronized Object design pattern

which describes a solution for the object synchronization concern.

� Silva et al.(1997b) presents the Recoverable Object design pattern which describes

a solution for the object recovery concern.

� Silva(1998) presents the three-layered architecture and object-oriented frame-

work with separation of concerns.

� Silva et al.(1999) presents the way the three-layered object-oriented framework

with separation of concerns can be described using design and composition pat-

terns.

� Silva(1997b) presents the pattern language. Is also describes a simplified version

of the Concurrent Object design pattern.

Part II

Separation of Concerns

59

4Concurrent Object Pattern

The Concurrent Object pattern supports various object concurrency policies. This

design pattern separates the object concurrency concern from object functionality.

4.1 Problem

Inter-object concurrency, in which several activities simultaneously execute in dif-

ferent objects, and intra-object concurrency, in which several activities simultaneously

execute within an object, allow performance to be potentially improved and concurrent

programming to be simplified.

It is necessary to define a construct which introduces concurrency in objects sup-

porting intra- and inter-object concurrency.

4.2 Analysis

A program is said to be concurrent if it has various interacting simultaneous exe-

cution flows of control. Interaction may be either through object sharing or message

passing. We will use the name activity for referring to the entity responsible for the

flow of control. An activity abstracts the mechanisms used to effectively create and

destroy flows of control such as threads.

Based on the kinds of constructs that objects integrate to create and destroy activi-

ties, described in section 2.2, three object concurrency policies can be identified:

61

62 CHAPTER 4. CONCURRENT OBJECT PATTERN

� In non-concurrent objects, activities executing on an object are not created, man-

aged, or destroyed by it. This policy should be used when there is no concurrency

between the client and server objects.

� Sequential objects have a single internal activity responsible for executing invoca-

tions. This policy should be used when there is concurrency between client and

server objects and each request’s execution time is short. The policy can also be

used to control a shared resource.

� Concurrent objects have several activities to execute concurrent invocations. This

policy should be used when there is concurrency between client and server ob-

jects and each request’s execution time is long. Regarding creation of internal

activities, several concurrent object types can be identified:

– A new activity is created when the concurrent object receives a message and is

destroyed when the request is satisfied.

– Internal activities are explicitly created and destroyed by the concurrent object.

Communication between objects is also part of the concurrency concern, for, as

mentioned in section 3.2.1, asynchronous communication and communication using

futures make sense, essentially, in the context of object concurrency. Thus, as described

in section 2.2, the following inter-object communication forms exist:

� One-way message passing allows transmission of information only from the caller

to the callee. These messages may be synchronous or asynchronous.

� In request/reply interactions, each request is associated with a reply. These mes-

sages may also be synchronous or asynchronous. In order to support asyn-

chronous messages future objects are used: client objects synchronize themselves

with invocation termination to receive results.

It should be noted that the use of futures assumes client objects to be aware of the

inter-object concurrency between the client and server objects. However, client objects

do not need to know which concurrency policy is used by the server object: sequential

object or concurrent object.

4.3. FORCES 63

4.3 Forces

An object-oriented solution for the object concurrency problem considers the forces

mentioned in section 3.2.2:

� Expressiveness. The Concurrent Object pattern must support the non-concurrent

object, sequential object, and concurrent object concurrency policies. All policies

may be associated with one-way message passing and request/reply communi-

cation, either synchronous or asynchronous. It should be noted that the non-

concurrent object policy is usually supported by the programming language.

� Modularity. The Concurrent Object pattern must separate concurrency from ob-

ject functionality. It should be noted that there is a conflict between modularity

and expressiveness, for concurrent objects with explicit activity creation have ac-

tivity generation primitives mixed with functionality.

� Encapsulation. The Concurrent Object pattern must centralize the responsibili-

ty for the functional object’s activity management, instead of it being divided

among its client objects.

� Reusability. The Concurrent Object pattern must allow object concurrency reuse

in different functional objects. Object functionality and concurrency must be sep-

arately extendible.

4.4 Structure and Participants

The class diagram presented in figure 4.1 illustrates the Concurrent Object pattern’s

class structure.

The participants in the Concurrent Object pattern are:

� Client Object. Uses the functional object’s services and obtains results

through the Future object.

64 CHAPTER 4. CONCURRENT OBJECT PATTERN

Interface

m() m’()

ObjectFunctionalConcurrency

Generator

start() status

MethodObject

execute()

Future

returnValues

putValue()getValue()available()isAvailable?()

ObjectClient

finish()

Figure 4.1: Structure of the Concurrent Object pattern.

� Functional Object. Contains the functionality to which concurrency is to be

added.

� Concurrency Interface. Is responsible for intercepting invocations from

the Client Object to the Functional Object and for associating them

with an object concurrency policy. It associates a Method Object with each

invocation. Uses the services provided by the Generator to create concurrency.

� Generator. Is responsible for creating activities and for associating them with

invocation execution. Operation start is responsible for associating an activity

with an invocation, before its execution. Operation finish is responsible for

deassociating the activity after invocation execution.

� Method Object. Represents an invocation. Contains the invocation’s contex-

t: the functional object, the operation to be invoked, and the invocation’s argu-

ments. It is responsible for triggering the invocation on the functional object,

through the execute operation, and for sending results to the Future object.

The invocation’s execution status is described by the status attribute, which

is NEW at creation time and before execution, EXEC during execution, and TERM

after execution.

4.5. COLLABORATIONS 65

� Future. Is responsible for containing the invocation’s result: the attribute re-

turnValues is used to that end. It is associated with asynchronous invocations.

The Client Object uses it to synchronize itself with execution termination

and to obtain the invocation’s results.

4.5 Collaborations

The collaborations between the pattern’s participants consist of two parts: invoca-

tion and acquisition of results, and invocation execution.

The collaborations in the sequence diagram, illustrated in figure 4.2, define the way

the client object starts the invocation and obtains its results.

a ConcurrencyInterface

a ClientObject

new()

m()

a Future

getValues()

isAvailable?()

Figure 4.2: Collaborations in the Concurrent Object pattern: invocation and acquisitionof results.

It is the Client Object’s responsibility to create a Future object and to send

it as an argument of invocation m on a Concurrency Interface. The client ob-

ject’s execution may occur simultaneously with the invocation’s, as depicted by the

dashed temporal bar. It is the client object’s responsibility to synchronize itself with

the end of the invocation and for obtaining its results. The IsAvailable? opera-

tion provides information on results availability. The getValues operation returns

66 CHAPTER 4. CONCURRENT OBJECT PATTERN

the results if they are available, otherwise it blocks the client object’s execution. Da-

ta is made available only after invocation of the available operation by a Method

Object (represented in figure 4.3). This operation releases the client object, if it had

been blocked when invoking getValues. It should be noted that the IsAvailable?

operation may be invoked several times as it does not block the client object.

The sequence diagram presented in figure 4.3 illustrates the collaborations for in-

vocation execution.

m()

new()

Interfacea Functional

Objecta Concurrency

a MethodObject

start()

execute()

execute()

finish()

m’()

putValue()

available()

a Generator a Future

Figure 4.3: Collaborations in the Concurrent Object pattern: invocation execution.

When an operation m is invoked by the client object on a Concurrency Inter-

face, a Method Object is created and passed to a Generator as argument of the

start operation. The invocation of the start operation on a Generator associates

an activity with the invocation and executes the execute operation of a Concur-

rency Interface, triggering the invocation’s execution in a Method Object. Af-

ter invoking the execute operation on a Method Object, the finish operation

deassociates the activity from invocation execution. Execution of the execute opera-

tion on a Method Object invokes the functional object and sends the results to the

Future object by invoking the putValues operation. The execution of the avail-

4.6. FORCES RESOLUTION 67

able operation on the Future object synchronizes the client object with the invoca-

tion’s termination.

4.6 Forces Resolution

This section shows how each of the forces presented in section 4.3 is solved. The

solution’s quality is thus shown.

4.6.1 Expressiveness

The Concurrent Object pattern supports the object concurrency policies identified in

the analysis section, with the exception of the concurrent object policy in which there

is explicit creation of activities, for this policy mixes functionality and concurrency.

The pattern’s expressiveness is achieved by specializing classes Generator,

Method Object, Future, and Concurrency Interface. Class Generator must

be specialized to support the object concurrency policies. Class Concurrency In-

terface must be specialized so that communication variants are expressed. Classes

Method Object and Futuremust be specialized with specific information about the

functional objects, their operations, and their arguments.

4.6.1.1 Sequential Object

Sequential objects have an internal activity responsible for repeatedly selecting and

executing pending invocations.

Figure 4.4 presents the specialization of class Generator for sequential objects.

Class Sequential Generator contains an internal activity and a list of Method

Objects pending execution. Class Activity represents an abstract concurrency

mechanism for activities. Class Activity’s spawn operation is responsible for trig-

gering the execution of the activity on the operation it receives as argument.

68 CHAPTER 4. CONCURRENT OBJECT PATTERN

GeneratorSequential Method

Object*invocations

internal

Activity

spawn()delete()

Figure 4.4: Structure Specialization for Sequential Object.

Figure 4.5 presents the collaborations associated with the specialization for sequen-

tial object.

new() internalActivity

spawn()

dispatch()

*{TRUE}

mo = nextInvocation()

new()

new()Interface

a Concurrency

a SequentialGenerator

execute()[mo]

insertInvocation()

start()

Figure 4.5: Collaboration Specialization for Sequential Object.

The operation creating a Sequential Generator must also create an internal

activity, through the asynchronous operation spawn, and initiate its execution, through

the dispatch operation. The dispatch operation executes in a loop reading Method

Objects from the queue of pending invocations and triggering their execution on a

Concurrency Interface. The second part of the collaboration diagram shows that

4.6. FORCES RESOLUTION 69

the start operation has only to insert the Method Object in the invocation-

s queue, for their association with the internal activity will be carried out when the

Method Object is selected for execution. It should be noted that the deassociation of

the activity from the invocation’s execution is guaranteed by the dispatch operation,

when it selects a new Method Object.

The executions of insertInvocation, by the client object’s activity, and of nex-

tInvocation, by the internal activity, constitute a mutual exclusion, for they concur-

rently access the queue of Method Objects.

4.6.1.2 Concurrent Object

The concurrent objects this pattern supports are those which implicitly create a

new activity for executing each invocation. Afterwards, this activity is also implicitly

destroyed, when the invocation finishes its execution.

A Generator subclass, Concurrent Generator, is defined. It creates activities

and associates them with invocation execution. Figure 4.6 presents the collaborations

associated with the specialization for concurrent object.

new()

spawn()

start()an Activity

Generatora Concurrent

delete()finish()

execute()

Interfacea Concurrency

Figure 4.6: Collaborations Specialization or Concurrent Object.

The start operation creates a new activity, through the asynchronous operation

spawn, which executes the a Concurrency Interface’s execute operation. The

70 CHAPTER 4. CONCURRENT OBJECT PATTERN

finish operation destroys the activity previously created by invoking the delete

operation on an Activity.

4.6.1.3 Non-Concurrent Object

Non-concurrent objects are those in which the activity executing the invocation

belongs to the client object. That is, the client object does not execute in parallel with the

functional object. This policy is usually supported by default by the object models of

programming languages. In order to support incremental development, the Concurrent

Object pattern must also allow specialization of non-concurrent objects1.

The non-concurrent object policy is supported by class Non-Concurrent Gen-

erator, which is a Generator subclass. The start operation does not need to asso-

ciate an activity with invocation execution: operation execute uses the client object’s

activity. The finish operation performs no actions and, thus, the activity continues

execution in the client object.

4.6.1.4 Communication Variants

The Concurrent Object pattern supports the following kinds of communication: one-

way, two-way, synchronous, asynchronous, and with futures. In addition, these vari-

ants are completely orthogonal to the object concurrency policies and, thus, all combi-

nations between communication variants and object concurrency policies are possible.

To obtain these variants it is enough to define different specializations of class Con-

currency Interface.

One-way or two-way message passing are trivially supported, for they depend

only on the definition of the functional object’s interface arguments.

By default, the pattern supports communication using futures. To support asyn-

chronous communication it is enough to associate a NULL Future object with the in-

vocation, i.e., the client object will not synchronize itself with the functional object. To

1In chapter 8 we will see how this specialization is used for incremental development.

4.6. FORCES RESOLUTION 71

support synchronous communication it is necessary for the Concurrency Inter-

face to encapsulate the synchronization between the client object’s activity and the

termination of the functional object’s activity. For that, the Concurrency Inter-

face object is responsible for creating a Future object and, immediately after invok-

ing start on the Generator object, must invoke getValues on the new Future

object. It should be noted that, in this variant, the Concurrency Interface object

offers the client object an interface equal to the functional object’s, thus making con-

currency transparent to the client object.

4.6.1.5 Concurrent Object: Explicit Creation

The Concurrent Object pattern does not support concurrent objects with explicit ac-

tivity creation (either when a message is received or through internal decision). The

main reason is that these policies mix functionality and concurrency and, thus, modu-

larity is lost.

Regarding expressiveness loss, it should be noted that it is possible for a clien-

t object to trigger concurrent execution of various activities by sequentially invoking

various functional objects having an interface with futures. That is, cobegin would

correspond to the different invocations and coend to synchronization with all future

objects. There are, nevertheless, differences regarding the use of cobegin ... co-

end:

1. Concurrency is in the functional objects and not in the client object which “explic-

itly” triggers it. That is, there is inter-object concurrency between the client object

and the functional objects. In addition, there may exist intra-object concurrency

if the functional objects support the concurrent object policy.

2. The client object assumes that concurrency exists, but it is, in fact, the functional

object’s responsibility to support it. For instance, the functional object may be

specialized with a non-concurrent object policy.

3. Concurrency granularity is at the object operation level and not at the procedure

or block levels.

72 CHAPTER 4. CONCURRENT OBJECT PATTERN

The fact that concurrency is the functional object’s responsibility, and not the client

object’s, allows the separation of functionality and concurrency. In addition, the client

object knows only about the “possible” concurrency, expressed by the Concurren-

cy Interface object. The client object’s functionality uses only the Future objects

without in fact mixing itself with concurrency code.

4.6.2 Modularity

The Concurrent Object pattern separates object concurrency from object functionali-

ty. Functionality is defined in the Functional Object while concurrency is defined

in the other objects. In particular, the Generator object supports object concurrency

policies. The Concurrent Interface object is responsible for integrating concur-

rency and functionality. However, it should be noted that the Method Object, which

has responsibilities in object concurrency definition, needs to know the functional ob-

ject’s interface.

4.6.3 Encapsulation

The Concurrent Object pattern centralizes the management of the functional objec-

t’s activities. The Concurrent Interface hides activity management from client

objects.

Encapsulation does not assume transparency, in which the client object ignores

the existence of concurrency in the functional object. Nevertheless, and depending on

how Concurrency Interface is defined, it is possible to have, or not, transparency.

Transparency is achieved when class Concurrency Interface offers an interface

similar to the functional object’s. In this situation, as previously mentioned, the Con-

currency Interface object must synchronize the client object’s activity with the

termination of the functional object’s activity, i.e., client objects do not create, before

the invocation, a Future object, neither do they receive one as result of an invocation.

It is important to emphasize that the Concurrent Object pattern encapsulates the

object concurrency policy but not the concurrency model. Client objects, when they

4.7. RELATED WORK 73

manipulate Future objects and use them for synchronization purposes, know that

the functional object is concurrent but ignore its object concurrency policy. That is,

for a given concurrency model, the Concurrent Object pattern encapsulates the policy

implementing that model.

4.6.4 Reusability

The Concurrent Object pattern allows separate reuse of object concurrency and func-

tionality due to its modularity. The functional object is separately extendible and may

be associated with various object concurrency policies. Generator subclasses may be

reused by any functional object for they are completely independent from them. Only

the customizations of classes Method Object and Future depend on the functional

object. Any functionality extension requires the definition of new Method Objec-

t and Future subclasses for each new functional operation. Nevertheless, and since

Method Object and Future subclasses are independent from Generator subclass-

es, they do not need to be changed when the object concurrency policy is changed.

The reuse problem described in section 2.5.2 does not occur. Class Sequential

Generator is separated from the functional class and is not reused through class in-

heritance, but rather through simple object composition.

4.7 Related Work

Threads libraries, such as the one described by Bershad et al.(1988), are approaches

to concurrency at the mechanism abstraction level. These libraries provide a set of con-

structs which allow creating, managing, and destroying threads. In these approaches,

concurrency constructs are defined orthogonally to objects, which implies that objects

are non-concurrent. Schmidt(1995) and Haines(1997) define libraries of abstract con-

currency mechanisms which are portable to various platforms.

Higher level approaches, either based on class libraries or language-based, restrict

expressiveness and composition, as mentioned in section 2.5.1 about ABCL/1, POOL-

74 CHAPTER 4. CONCURRENT OBJECT PATTERN

T, Eiffel, Karaorman & Bruno(1993), and ABC++. It should be noted that the two

library-based approaches, Karaorman & Bruno(1993) and ABC++, do not support con-

current objects.

It can be concluded that adequate relevance has not been given to object con-

currency by the various approaches to concurrent programming. Recent separation

of concerns approaches either do not consider concurrency responsible for code tan-

gling (Lopes, 1997) or mix concurrency constructs with the functional part (Aksit et al.,

1994a).

The aspect-oriented programming approach to concurrency, proposed by

Lopes(1997), considers that the creation of new threads does not lead to code tangling,

for it consists of an invocation of a threads library with no consequence other than the

generated thread. It can, thus, be concluded that this approach does not consider the

complexity of sequential objects and of concurrent objects and is, thus, built on top of

a uniform model of non-concurrent objects.

Composition filters (Aksit et al., 1994a), which associate a filter with each concern,

do not have a filter for concurrency: activity generation is carried out within the func-

tional object. Two ways of generating concurrency are provided: (i) when an object

is created it may have an internal activity; and (ii) an early-return primitive is pro-

vided. Concurrency is generated by using the early-return primitive, for when the

client object performs an invocation, the functional object may return a result before

terminating, i.e., an early result. This makes concurrent execution of the client and

functional objects possible. The early-return primitive allows the implementation of

synchronous communication when the functional object makes the return of a value

to the client coincident with the end of the execution. Asynchronous communication

is also allowed: the functional object returns a result immediately after receiving a re-

quest. Using early-return, concurrency is transparent for the client object, but within

the functional object, object concurrency is not separated from functionality, making

it impossible to change the object concurrency policy without changing the functional

object.

The Actalk object-oriented framework (Briot, 1989) does not support non-

4.8. RESULTS 75

concurrent objects. All objects have an internal activity. Nevertheless, this internal

activity is responsible for selecting the next invocation to be executed, and may trigger

the execution of the selected invocation using a new activity. When invocation execu-

tion is carried out by the internal activity, a sequential object is obtained, otherwise a

concurrent object with an internal activity is obtained. It should be noted that the lat-

ter is slightly different from the concurrent objects supported by the Concurrent Object

pattern.

Finally, a reference should be made to the Active Object pattern, described by Laven-

der & Schmidt(1996), which corresponds to the specialization of the Concurrent Object

pattern for sequential objects.

4.8 Results

The Concurrent Object pattern describes a solution for object concurrency which

separates object concurrency from functionality. This pattern allows the definition of

non-concurrent, sequential, and concurrent objects, as well as various forms of both

synchronous and asynchronous communication. The pattern makes it possible to sep-

arately reuse concurrency and functionality. In particular, the Generator object de-

fines generic concurrency policies which may be used by different functional objects.

The Concurrent Object pattern encapsulates concurrency within the functional object

allowing, nevertheless, various concurrency models. The pattern is described using

only the basic object-oriented programming concepts. It may be implemented using

any object-oriented language.

The pattern was designed after an in-depth study of the state of the art and has

unique qualities, either in the context of approaches based on class libraries or in the

context of language-based approaches.

Silva(1997b) describes an initial version of the pattern, supporting sequential ob-

jects.

76 CHAPTER 4. CONCURRENT OBJECT PATTERN

5Synchronized Object

Pattern

The Synchronized Object pattern supports various object synchronization policies.

It separates the object synchronization concern from object functionality.

5.1 Problem

Object invocations must be synchronized either because their concurrent execu-

tion may corrupt an object’s state or because their execution may not be possible in the

object’s current state. For instance, the result of concurrently executing two write oper-

ations on an attribute may not be the same obtained by any of their possible sequential

executions. In addition, an empty list cannot execute an operation requiring an item.

5.2 Analysis

As described in 2.2, there are several kinds of construct for object synchronization:

� In unconditional acceptance objects do not have their own object synchronization

constructs.

� In conditional acceptance objects integrate synchronization constructs which may

delay invocation execution in order to control execution order. There are several

conditional acceptance constructs:

– In explicit acceptance, the accept construct denotes invocation acceptance.

77

78 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

– Activation conditions define the states in which operation execution may be

accepted. The enabled set and the guard are two of these synchronization

constructs. In the former, each operation defines, at the end of its execution,

which operations may be executed next. In the latter, an execution precon-

dition is associated with each operation.

The constructs above must satisfy the expressiveness requirement stated in sec-

tion 2.5.1. Various object synchronization policies exist which must be supported by

these constructs:

� Pessimist and Optimist Synchronization. These policies define generic synchro-

nization strategies. Pessimist policies synchronize object invocations before they

occur, while optimist policies verify execution order after their execution. The

former must be used when a high degree of object access conflicts exists, while

the latter are applicable when conflicts are less frequent.

� Synchronization Based on Invocation State. The synchronization policy may

use the state of invocations on an object: at a given time, an invocation may

be pending, in execution, or finished. For instance, the readers/writers policy

delays execution of a write invocation if a read invocation is executing.

� Synchronization Based on Object State. An object may have states in which it

is not possible for it to satisfy some invocations. It is the synchronization pol-

icy’s responsibility to verify if the invocation must be delayed, until the object

reaches a future state capable of satisfying the invocation, or must be aborted,

when there are no future states capable of satisfying the invocation. For instance,

the producer/consumer policy delays execution of an invocation requesting a

resource whenever resources are unavailable.

� Dynamic Change of Synchronization Information. The synchronization policy

may dynamically change synchronization information, such as priority associat-

ed with pending invocations. For instance, a policy which synchronizes accesses

to a shared resource, e.g. a printer, which satisfies invocations based on priori-

ty, e.g. small files are printed first. This policy dynamically changes the priority

5.3. FORCES 79

associated with pending invocations to avoid invocation starvation, e.g. large

requests could be starved by small requests.

As seen in the examples above, synchronization policies need information to syn-

chronize invocations. As referred in section 2.5.1, Bloom(1979) enumerates six types

of synchronization information needed by a vast number of policies: invocation type,

invocation order, invocation arguments, state of pending and executing invocations,

object state, and invocation history.

On the other hand, object synchronization support constructs must, in addition,

satisfy the reusability requirement stated in section 2.3. As referred in section 2.4.1,

a conflict exists between inheritance and synchronization, known in the literature

as the inheritance anomaly problem (Matsuoka & Yonezawa, 1993). Nevertheless, M-

cHale(1994) shows that the so called inheritance anomaly results from using inheri-

tance for two purposes: functionality reuse and synchronization reuse.

McHale also shows that, even when synchronization code is structurally separated

from functionality code, if synchronization constructs have a limited expressive power,

not supporting, for instance, the six types of synchronization information enumerat-

ed by Bloom, then it is necessary to use functional code to preserve desired synchro-

nization information, hence losing the separation between functionality and synchro-

nization. For instance, if synchronization constructs do not support the definition of

synchronization variables, then it is necessary to define these variables in the function-

al code, as in the case of variable after put, described in section 2.4.1, to preserve

information about invocation history.

5.3 Forces

An object-oriented solution for the object synchronization problem considers the

forces mentioned in section 3.2.2:

� Expressiveness. The Synchronized Object pattern must support object synchro-

80 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

nization policies. For that, the pattern must support the six types of synchroniza-

tion information enumerated by Bloom.

� Modularity. The Synchronized Object pattern must separate object synchroniza-

tion from object functionality. It should be noted that explicit acceptance con-

structs present modularity limitations, for the body with the accept constructs

is mixed with the functionality.

� Encapsulation. The Synchronized Object pattern must centralize the functional

object’s synchronization, instead of it being divided among its client objects. In

this way, synchronization is the functional object’s responsibility. Negligence on

the clients part is thus avoided. For instance, in unconditional acceptance, client

objects may use a global semaphore variable to synchronize accesses to the func-

tional object. If a client forgets to release the semaphore a deadlock situation

occurs.

� Reusability. The Synchronized Object pattern must allow synchronization and

functionality to be independently reused and extended. The solution must avoid

the inheritance anomaly problem.

5.4 Structure and Participants

The class diagram presented in figure 5.1 illustrates the class structure of the Syn-

chronized Object pattern:

The Synchronized Object pattern’s participants are:

� Client Object. Uses the functional object’s services.

� Functional Object. Is responsible for providing functionality whose invo-

cation must be synchronized.

� Synchronization Interface. Is responsible for intercepting Client Ob-

ject invocations to the Functional Object associating with it a synchroniza-

5.4. STRUCTURE AND PARTICIPANTS 81

SynchronizationPredicate

status

require()preGuard()postGuard()pre()exec()post()commit()abort()

ClientObject

DataSynchronization

m’()

ObjectFunctionalSynchronization

Interface

m()

Synchronizer

preControl()postControl()

*invocations

Figure 5.1: Structure of the Synchronized Object pattern.

tion policy. Associates a Synchronization Predicate object with each invo-

cation. Uses the Synchronizer’s services.

� Synchronizer. Is responsible for synchronizing invocations. Operations pre-

Control and postControl are responsible for controlling invocation execution

order, being able to delay or abort invocations.

� Synchronization Predicate. Represents an invocation. Contains the in-

vocation’s execution state and its synchronization specific information, e.g. the

value of the invocation’s arguments. An invocation’s execution state is described

by the status attribute. It has value PRE, if the invocation is pending execu-

tion; EXEC, if the invocation is executing functional code; POST, if the invocation

has finished execution and is pending; COMMIT, if the invocation has finished

successfully; and ABORT, if the invocation has finished unsuccessfully. In ad-

82 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

dition, Synchronization Predicate contains the list of all synchronization

predicates: invocations. Operations require, preGuard, and postGuard

are responsible for ensuring the invocation’s synchronization. Operation re-

quire controls accesses based on the object’s state, while operations preGuard,

and postGuard base their actions on the execution state of other invocations.

Operations pre, exec, post, commit, and abort are responsible for updating

synchronization information.

� Synchronization Data. Is responsible for centralizing synchronization in-

formation. For instance, it may contain the definition of abstract synchronization

states, such as the buffer states of empty, partial, and full, or the number of

invocations pending execution.

5.5 Collaborations

The collaborations between pattern participants have a generic part, common to

all synchronization policies, and a part which changes according to the policy. The

sequence diagram presented in figure 5.2 illustrates the part common to all collabora-

tions between the Synchronized Object pattern’s participants.

A collaboration’s generic part is divided into the four phases described below:

1. CREATE. When an operation is invoked on the synchronization interface, a new

Synchronization Predicate object is created. Operation pre is invoked to

update synchronization information which, in particular, updates the status

execution state attribute to PRE.

2. PRE-CONTROL. This phase is responsible for synchronizing an invocation with

state PRE. During this phase, it invokes operations require and preGuard. If

the value returned by an operation is ERROR1 then the invocation should termi-

nate without accessing the functional object. Otherwise, if the value returned

1In section 5.6.3 we will see the possible consequences an ERROR return value has on client objects.

5.5. COLLABORATIONS 83

m()

new()Predicate

a Synchronization

a SynchronizerInterface

a Synchronization

pre()CR

EA

TE

exec()

xStatus = require()

xStatus = preGuard()

abort()

xStatus = preControl()

PRE

-CO

NT

RO

L

m’()

xStatus = postControl()xStatus = postGuard()

abort()

commit()

post()

POST

-CO

NT

RO

LE

XE

CU

TIO

N

a FunctionalObject

*{xStatus==DELAY}

[xStatus==CONTINUE]

[xStatus==CONTINUE]

[xStatus==ERROR]

*{xStatus==DELAY}

[xStatus==DELAY]

[xStatus==CONTINUE]

[xStatus==ERROR]

Figure 5.2: Synchronized Object pattern collaborations: generic part.

by an operation is DELAY then access to the functional object should be delayed.

Finally, if both operations return CONTINUE the invocation may proceed on the

functional object. Operations exec and abort are executed to update synchro-

nization information, according to the value returned by, respectively, CONTIN-

UE and ERROR. In particular, these operations update the status execution state

attribute to EXEC and ABORT, respectively. This phase is repeated for each invo-

cation while the returned value is DELAY.

3. EXECUTION. In this phase, which occurs after and if the previous phase returns

CONTINUE, the invocation executes on the functional object.

4. POST-CONTROL. This phase verifies if an invocation which has terminated its

84 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

access to the functional object is correctly synchronized. The verification proto-

col is the postGuard operation’s responsibility. Synchronization information is

updated by operations post, commit, and abort if the value returned by the

postGuard operation is, respectively, DELAY, CONTINUE, and ERROR. In partic-

ular, these operations update the status execution state attribute to, respective-

ly, POST, COMMIT, and ABORT. This phase is repeated for each operation while

the returned value is DELAY.

To simplify the diagram, figure 5.2 does not show that the EXECUTION and POST-

CONTROL phases are not executed if the PRE-CONTROL phase returns ABORT.

Operations pre, preControl, and postControl must be executed in mutual

exclusion, for their concurrent execution would result in synchronization information

corruption. The mutual exclusion is not shown in figure 5.2.

The collaborations triggered by pre, exec, post, abort, and commit opera-

tions, which update synchronization information, and by the require, preGuard,

and postGuard operations, which verify synchronization correctness2 vary according

to the adopted synchronization policy, as will be shown in section 5.6.1. Nevertheless,

a general collaboration archetype exists (see figure 5.3). Operations involved in collab-

orations are policy-specific and are represented generically, in figure 5.3, as read and

update operations.

In the top collaboration, synchronization predicates (*finvocationsg) associated

with invocations are accessed. In the bottom collaboration, the object which central-

izes the synchronization state information is accessed. In this second collaboration, the

functional object may also be accessed for reading. However, this interaction has con-

sequences which will be discussed in the following section, for it corresponds to the

situation in which the values of the functional object’s attributes are used as synchro-

nization information. Depending on the specific synchronization policy, one or both

collaborations may occur. Their order is irrelevant when both occur.

2These operations read synchronization information and never change it.

5.6. FORCES RESOLUTION 85

PredicateSynchronization

another

read/updateSYNCHRONIZATION DATA

SYNCHRONIZATION DATAREAD FUNCTIONAL OBJECT

a SynchronizationPredicate

a SynchronizationPredicate

*{invocations}read/updateREAD/UPDATE INVOCATION

SYNCHRONIZATION DATA

a FunctionalObjectData

a Synchronization

read

READ/UPDATE

Figure 5.3: Collaborations of the Synchronized Object pattern: policy-specific part.

5.6 Forces Resolution

In this section we describe the way each of the forces presented in section 5.3 is

solved, thus showing the solution’s quality.

5.6.1 Expressiveness

The Synchronized Object pattern supports all synchronization policies identified

during the analysis phase.

The pattern’s expressiveness is achieved by specializing classes Synchronizer,

Synchronization Predicate, and Synchronization Data.

The pattern’s specializations support the six synchronization information types

enumerated by Bloom. Specializations of class Synchronization Predicate are

able to support information on invocation type, invocation order, invocation argu-

ments, and state of pending and executing invocations. Specializations of class Syn-

chronization Data are able to support information on object state and invocation

history. Moreover, the pattern allows this information to be changed whenever there

86 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

is a change in synchronization conditions: when an invocation is submitted, when it

starts executing, when it finishes executing, when it aborts, and when it commits. The

updates are carried out by, respectively, the pre, exec, post, commit, and abort

operations.

Pessimist and optimist policies are generic synchronization strategies which are

used jointly with more specific policies, such as, for instance, readers/writers. Below,

it is shown how the pattern supports these two generic policies.

The definition of pessimist and optimist policies is achieved by specializing Syn-

chronizer. On the left hand side of figure 5.4 the collaborations associated with

pessimist policies are described, while on the right hand side the ones associated with

optimist policies are described.

exec()

xStatus = require()

xStatus = preGuard()

abort()

preControl()

a PessimisticSynchronizer Predicate

a Synchronization

postControl()

xStatus = require()preControl()

a OptimisticSynchronizer Predicate

a Synchronization

postControl()commit() xStatus = postGuard()

post()

commit()

abort()

exec()

abort()

[xStatus==CONTINUE]

[xStatus==CONTINUE]

[xStatus==ERROR]

[xStatus==CONTINUE]

[xStatus==ERROR]

[xStatus==DELAY]

[xStatus==CONTINUE]

[xStatus==ERROR]

Figure 5.4: Specialization for Pessimist and Optimist Policies.

Pessimist policies verify correctness during the PRE-CONTROL phase. During the

POST-CONTROLphase it is unnecessary to perform further verifications. Optimist poli-

cies verify correctness during the POST-CONTROL phase. It should be noted that the

5.6. FORCES RESOLUTION 87

require operation is also invoked in optimist policies to verify if the object’s state

allows invocation execution. For instance, the get operation cannot occur if a buffer

object is empty.

5.6.1.1 Readers/Writers Policy

The readers/writers policy synchronizes each invocation taking into account the

state of the other invocations. In this policy two categories of functional object opera-

tions are considered: read and write. The policy allows concurrent execution of read

operations but prevents concurrent execution of a write operation when other read or

write operations are being executed.

Figure 5.5 represents the pattern’s specialization for a pessimist readers/writers

policy.

ReadPredicate Predicate

Write

category

getCategory()

PredicateRead/Write

Predicatea Read/Write

Predicatea Read

preGuard() *{invocations}

s = getStatus()

DELAY

CONTINUE

Predicatea Read/Write

Predicatea Write

preGuard() *{invocations}

s = getStatus()

DELAY

CONTINUE[s==EXEC && c==WRITE]

[s===EXEC]

[category==READ] [category==WRITE]

c = getCategory()

Figure 5.5: Specialization for Readers/Writers (Pessimist).

Class Synchronization Predicate is specialized by a Read/Write Predi-

88 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

cate class which generalizes two predicates: Read Predicate and Write Pred-

icate. These predicates are associated with, respectively, the functional object’s read

and write operations.

The collaboration on the lower left corner of figure 5.5 shows the interactions asso-

ciated with the preGuard operation of the Read Predicate. The preGuard oper-

ation returns DELAY if an executing write invocation exists; otherwise it returns CON-

TINUE.

The collaboration on the lower right corner of figure 5.5 shows the interactions

associated with the preGuard operation of the Write Predicate. The preGuard

operation returns DELAY if either a read or write invocation is executing; otherwise it

returns CONTINUE.

It should be noted that the require operation returns CONTINUE for both pred-

icates and that synchronization information update operations have the previously

described default behavior.

Figure 5.6 represents the pattern’s specialization for an optimist readers/writers

policy.

In contrast with the pessimist policy, class Read/Write Predicate has an addi-

tional attribute: abort. This attribute indicates whether the corresponding invocation

should abort.

The collaboration on the upper right corner of figure 5.6 defines the postGuard

operation, common to both read and write predicates. The postGuard operation re-

turns ERROR if the abort attribute is true and CONTINUE otherwise. The collabora-

tions at the bottom of figure 5.6 show the conditions in which the abort attribute is

set to true.

The collaboration on the lower left corner of figure 5.6 shows the interactions as-

sociated with the commit operation of the Read Predicate. The commit operation

is invoked as a result of postGuard returning continue. The commit operation in-

vokes setAbort in the predicates of executing write invocations. These invocations

will, thus, abort during the POST-CONTROL phase.

5.6. FORCES RESOLUTION 89

Predicate

ERROR[abort]

postGuard()

CONTINUE[NOT abort]

a Read/Write

category

PredicateRead/Write

abort

getCategory()setAbort()

ReadPredicate Predicate

Write

a Read/WritePredicatePredicate

a Read

commit()

s = getStatus()*{invocations}

setAbort()

c = getCategory()

Predicatea Read/Write

Predicatea Write

commit()

s = getStatus()*{invocations}

setAbort()

[category==READ] [category==WRITE]

[s==EXEC && c==WRITE]

[s==EXEC]

Figure 5.6: Specialization for Readers/Writers (Optimist).

The collaboration on the lower right corner of figure 5.6 shows the interactions

associated with the commit operation of the Write Predicate. The commit opera-

tion invokes setAbort in the predicates of executing invocations.

As in the pessimist policy, the require operation returns CONTINUE and the syn-

chronization information update operations change the status attribute accordingly.

The optimist readers/writers policy has to be combined with a specific object re-

covery policy: the deferred update policy. In this object recovery policy, described in

chapter 6, concurrent invocations occur in object copies, for simultaneous access by

several entities to the object’s attributes may result in abnormal activity termination.

90 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

5.6.1.2 Dynamic Priority Policy

The pessimist readers/writers policy allows starvation of write operations. In or-

der to avoid this situation, a readers/writers policy is defined in which priorities are

dynamically associated with invocations. Write invocations have associated priorities

which dynamically increase with the execution of read operations. A read operation

must be delayed if there is a write operation with maximum priority pending execu-

tion.

Figure 5.7 represents the pattern’s specialization for a pessimist dynamic priority

policy.

CONTINUE

DELAY

ReadPredicate Predicate

Write

category

getCategory()

PredicateRead/Write

priority

incPriority()

getPriority()

Predicatea Read/Write

Predicatea Read

preGuard() *{invocations}

s = getStatus()

p = getPriority()

c = getCategory()

DELAY

CONTINUE

Predicatea Read/Write

Predicate

preGuard() *{invocations}

s = getStatus()

c = getCategory()

p = getPriority()

a Write

Predicatea Read/Write

Predicate

*{invocations}

s = getStatus()

exec()

c = getCategory()

incPriority()

a Read

[category==READ] [category==WRITE]

[s==PRE && c==WRITE]

[c==WRITE]

[(s==EXEC && c==WRITE) ||(s==PRE && c==WRITE && p==MAX)]

[c==WRITE]

[(s==EXEC) ||(s==PRE && c==WRITE && priority<p)]

Figure 5.7: Specialization for Dynamic Priority.

Regarding the pessimist readers/writers policy, class Write Predicate has a

new attribute: priority. This attribute contains the priority associated with the write

5.6. FORCES RESOLUTION 91

operation and is initialized upon predicate creation. The incPriority operation is

responsible for incrementing the attribute’s value.

The three collaboration diagrams in figure 5.7 represent policy changes in relation

to the previous version. On the lower left corner are described the interactions trig-

gered by the Read Predicate’s preGuard operation. It should be noted that now

the read operation is also delayed if a write operation with maximum priority exists

pending execution. In contrast, the Write Predicate’s preGuard operation, rep-

resented on the lower right corner of figure 5.7, must return CONTINUE if there is no

executing operation and it has the highest priority of all write predicates pending ex-

ecution. The Read Predicate’s exec operation is represented on the upper right

corner of figure 5.7. This operation increments the priority attribute’s value of all

Write Predicates pending execution. The exec operation is executed whenever a

read operation starts execution.

The dynamic priority policy is an example of a policy which allows dynamic up-

date of synchronization information: in this particular case, the priority attribute’s

value.

5.6.1.3 Producer/Consumer Policy

The producer/consumer policy synchronizes invocations taking into account the

functional object’s state. Two operation categories are considered: produce and con-

sume. The policy delays the execution of consume operations if there are no available

items and delays the execution of produce operations if the functional object does not

have enough available space for storing new items.

Figure 5.8 represents the pattern’s specialization for a pessimist produc-

er/consumer policy.

Class Synchronization Predicate is specialized by a Producer/Consumer

Predicate which generalizes two predicates: Produce Predicate and Consume

Predicate. These predicates are associated with, respectively, the functional object’s

produce and consume operations. Class Synchronization Data is specialized by

92 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

Predicate Data

a BufferSynchronizationa Produce

require()b = isFull()

DELAY

CONTINUE

Predicate Data

a BufferSynchronizationa Consume

require()

DELAY

CONTINUE

b = isEmpty()

Predicate Predicate

category

getCategory()

PredicateProducer/Consumer

Produce Consume

SynchronizationData

Buffer

[category==PRODUCE] [category==CONSUME]

[b==TRUE]

[b==FALSE]

[b==TRUE]

[b==FALSE]

SynchronizationData

isFull()isEmpty()

Figure 5.8: Specialization for Producer/Consumer.

class Buffer Synchronization Data which is responsible for indicating if the

functional object is full or if it is empty, through the isFull and isEmpty operations,

respectively.

In this policy, it is necessary to define only the synchronization predicates’ re-

quire operation. A collaboration in which a produce operation is delayed if the

Buffer is full is described on the lower left corner of figure 5.8. On the lower right

corner a collaboration is described for the case of a consume operation on an empty

Buffer.

5.6.1.4 Synchronization Counters

There are several object synchronization policies which use synchronization coun-

ters. Synchronization counters register, for each invocation type, the number of pend-

ing, executing, and finished invocations.

The Synchronized Object pattern easily supports synchronization counters by spe-

5.6. FORCES RESOLUTION 93

cializing class Synchronization Data, to store the counters, and by specializing

class Synchronization Predicate, to update the counters’ values by using the

pre, exec, post, commit, and abort operations. The supported counters for each

invocation type are: pending before execution; executing; pending after execution;

successfully terminated; and unsuccessfully terminated.

It should be noted that synchronization counters may be used for implementing

readers/writers policies. Using synchronization counters, it is unnecessary to consult

the invocations list to determine if there are executing read or write predicates.

5.6.1.5 Enabled Sets

The Synchronized Object pattern also supports enabled sets.

The enabled set is defined in class Synchronization Data. Determining the

next enabled set after the end of each operation is the responsibility of the predicates’

commit and abort operations. To choose the next operation to be executed it is e-

nough to define the Synchronization Predicate’s require operation, so that it

returns CONTINUE when the predicate belongs to the enabled set in Synchroniza-

tion Data, and DELAY otherwise. It is necessary to define the preGuard and post-

Guard operations of all Synchronization Predicates so that they return CON-

TINUE.

Thomas(1994) argues that enabled sets are useful for specifying service availability

while guards are useful for specifying intra-object concurrency, respectively, synchro-

nization based on the object’s state and synchronization based on the state of invoca-

tions. Thus, Thomas concludes that synchronization policies must integrate both con-

structs. The Synchronized Object pattern integrates both constructs in a single policy,

for the require operation is associated with object state-based synchronization and

the preGuard and postGuard operations are associated with invocation state-based

synchronization.

94 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

5.6.2 Modularity

The Synchronized Object pattern separates synchronization from object functionali-

ty. Synchronization is contained within classes Synchronizer, Synchronization

Predicate, and Synchronization Data. Functionality is contained within class

Functional Object. The integration of synchronization and functionality is the re-

sponsibility of class Synchronization Interface.

However, it is not obvious that modularity in fact occurs when the functional ob-

ject’s attributes are used as synchronization information. The upper part of figure 5.9

shows one such scenario. The information on the number of items in a Buffer is

contained within the functional object.

b = isFull()num = getNumItems()

TRUE

FALSE

Data

a BufferSynchronization

incNumItems()

Data

a BufferSynchronizationa Produce

Predicate

commit()

Data

a BufferSynchronization

b = isEmpty()num = getNumItems()

TRUE

FALSE

decNumItems()

Data

a BufferSynchronization

exec()

Predicatea Consume

[num==0]

[num>0]

[num==size]

[num<size]

a Buffer a Buffer

Figure 5.9: Specializations of Class Synchronization Data.

This modularity break has two undesirable consequences: (i) Functional Ob-

jects must allow access to synchronization information to Synchronization Da-

ta objects; (ii) the execution of synchronization code may conflict with the execution

of an invocation on the object when both access the same variables.

The first consequence penalizes incremental introduction of synchronization, for

the functional object must be changed in order to allow access to synchronization in-

5.6. FORCES RESOLUTION 95

formation. It should be noted that this access may be obtained either by extending the

functional object’s interface with the necessary operations or by allowing Synchro-

nization Data objects access to the internal structure of functional objects, using

something similar to the friend qualifier of the C++ language. For instance, in fig-

ure 5.9, class Buffer has been extended with the getNumItems operation.

The second consequence forces re-evaluation of the synchronization conditions as-

sociated with the operations. This re-evaluation leads necessarily to a reduction of the

achieved concurrency degree. For instance, consume and produce operations conflict

if they use as synchronization information the number of items contained within the

functional object, for while one is reading it, during the PRE-CONTROL phase, the other

may be, in the EXECUTION phase, changing it.

It can be shown, however, that the pattern allows complete separation of synchro-

nization and object functionality, even when synchronization is based on the objec-

t’s state. An example of this solution is represented in the bottom part of figure 5.9.

Class Buffer Synchronization Data has an attribute which counts the number

of items in a Buffer. Thus, synchronization information is not on the functional

object. It is now necessary to change the synchronization predicates so that they in-

crement the attribute whenever a produce operation successfully terminates execution

(operation commit), and decrement the attribute before a consume operation starts

executing (operation exec). As the commit and exec operation execute in mutual

exclusion, there are no conflicts between produce and consume invocations.

5.6.3 Encapsulation

The Synchronized Object pattern centralizes the functional object’s synchronization.

The Synchronization Interface object encapsulates synchronization, hiding it

from client objects. The negligence situations mentioned in section 5.3 are thus avoid-

ed.

As in the Concurrent Object pattern, encapsulation does not assume transparency,

i.e., it is not assumed that client objects ignore the existence of synchronization. Syn-

96 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

chronization transparency depends on how the Synchronization Interface is

defined. When the Synchronizer returns ERROR, the Synchronization Inter-

face object may resubmit the invocation or return the error to the client. In the latter

case there is no transparency, for the client is aware of a synchronization problem.

It should be noted that synchronization errors are not necessarily due to concurren-

cy situations. They may occur in a sequential program. For instance, when a sequential

program attempts to remove an item from an empty buffer.

Thus, the Synchronized Object pattern encapsulates the synchronization policy but

not the synchronization model. For a given synchronization model, the Synchronized

Object pattern encapsulates the specific policy which implements that model.

5.6.4 Reusability

The presented solution allows separate reuse of object synchronization and func-

tionality due to modularity. That is, it is possible to associate the same synchroniza-

tion policy with different functional objects and different synchronization policies with

the same functional object. For instance, the read/write predicates may be used for

synchronizing different functional objects: it is enough to associate with each of the

functional object’s operations the correct synchronization predicate. In the same way,

different synchronization policies may be associated with the same functional object.

For instance, a mutual exclusion policy and a readers/writers policy may be associated

with the same functional object.

Moreover, when modularity is not complete, i.e., when the specializations of class

Synchronization Data access the functional object knowing its operations’ iden-

tifiers, or even its internal structure, it is enough to redefine the specialization of class

Synchronization Data to adapt the synchronization policy to the functional objec-

t.

In addition, the pattern offers solutions to the inheritance anomaly problem. The

problem occurs when introducing a new operation in a subclass, or when redefining

an operation. It leads to the redefinition of other operations supposedly independent

5.6. FORCES RESOLUTION 97

from the introduced or redefined operation.

The typical inheritance anomaly scenarios, identified by Matsuoka & Yoneza-

wa(1993), and described in section 2.4.1, are solved by the Synchronized Object pattern:

� Partitioning of states occurs when a new operation, having a new acceptance state,

is introduced. For instance, introduction of the get2 operation in class Buffer

requires the existence of an acceptance state in which the number of Buffer

items is greater than or equal to two. The pattern easily solves this situation

through the definition of a new predicate whose require operation returns DE-

LAY if the number of items is zero or one. The specialization of class Synchro-

nization Data must have an operation which returns the number of items.

� History-only sensitiveness of states occurs when a new operation is introduced

whose synchronization requires knowledge of the history of past invocations.

For instance, the introduction of the gget operation which may execute only if,

immediately before, a put operation has not occurred. To solve this situation it is

necessary to define a new predicate and to extend the specialization of class Syn-

chronization Data in order to provide operations to register the occurrence

of the put operation. In addition, it is necessary to extend the commit oper-

ation of each predicate in order to update the synchronization information, in

Synchronization Data, with the information on which operation has more

recently occurred.

� Composition of synchronization code occurs when a synchronized class is enriched

with more synchronization code. For instance, the enrichment of the synchro-

nized Buffer class with the lock synchronization scheme. The lock synchro-

nization scheme consists of two predicates, Lock and Unlock, and a Synchro-

nization Data specialization containing an attribute indicating if the object is

locked. To solve this problem, it is necessary to compose the specializations

of Synchronization Data and to extend the require operation of each of

the predicates associated with Buffer so that they return DELAY if the object is

locked, and invoke the superclass’ require operation otherwise.

98 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

It should be noted that, regarding the previous situations, whenever a new predi-

cate is introduced, and whenever synchronization takes into account the state of other

invocations, it is necessary, in addition, to extend the preGuard and postGuard op-

erations of the other predicates so that they consider the existence of the new predicate.

It can, thus, be concluded that, generally, the previous synchronization can be

reused. Also, it can be seen that the ease of synchronization reuse depends on how

the synchronization predicates’ operations are coded; however, generally it is enough

to extend them. This result is obtained because the pattern satisfies the two require-

ments stated by McHale(1992): synchronization is separated from functionality, and it

is possible to separately reuse parts of the synchronization code (Synchronization

Predicate and Synchronization Data).

5.7 Related Work

As mentioned in section 2.5, approaches to concurrent object-oriented program-

ming have problems concerning synchronization reuse, expressiveness, and mod-

ularity. Approaches in which synchronization is monolithic (Campbell & Haber-

mann, 1974), or in which synchronization is not separated from functionality (Nier-

strasz, 1987; Kafura & Lee, 1989; Tomlinson & Singh, 1989), or in which synchroniza-

tion and functionality are located in the same class, even though they are separat-

ed (American National Standards Institute, 1983; Grass & Campbell, 1986; Caromel,

1990a; Decouchant et al., 1991), have inheritance anomaly problems. There are ap-

proaches which, despite separating functionality and synchronization in different en-

tities (Atkinson et al., 1991; Neusius, 1991; Baquero et al., 1995), have expressiveness

problems due to the limited expressive power of their synchronization constructs. In

these approaches, when a synchronization construct uses the functional part to handle

an expressive power limitation, modularity problems arise (Atkinson et al., 1991).

McHale(1994), following McHale et al.(1991), presents an object synchronization

language which has three properties: expressiveness, modularity, and reusability. Ex-

pressiveness is achieved, for it supports the six synchronization information type-

5.7. RELATED WORK 99

s enumerated by Bloom(1979). Modularity is achieved, for synchronization is sepa-

rated from functionality and the synchronization code never accesses functional vari-

ables. The complete separation allows the definition of generic synchronization poli-

cies which may be reused in various functional objects since they are completely in-

dependent from them. Reusability results from the capability to incrementally extend

synchronization constraints and from being able to separately reusing functionality

and synchronization. The design of the Synchronized Object pattern has had as its s-

tarting point the principles and features of the synchronization language presented by

McHale. In addition, the pattern includes support for optimist policies and for report-

ing invocation synchronization errors.

The approach to aspect-oriented programming by Lopes(1997), following previous

work on synchronization (Lopes & Lieberherr, 1994), proposes a synchronization lan-

guage which is separated from functionality. In this language, synchronization code

accesses the functional object’s variables and uses its operations’ names. These two

features do not allow synchronization code to be reused by different functional ob-

jects, thus reducing the possibility of synchronization reuse and of defining generic

synchronization policies. The main argument presented by the authors is that synchro-

nization is intrinsically dependent on the functional object’s implementation and thus

it is important to make functionality independent from synchronization and not the

reverse. For instance, the decision on whether to allow the get and put operations to

occur simultaneously depends on the way the buffer is implemented. However, syn-

chronization being in fact implementation-dependent does not prevent the existence of

generic policies reusable by different objects (implementations). The Synchronized Ob-

ject pattern allows the definition of generic policies, but it also allows the definition,

whenever necessary, of customizations for each specific case.

Composition filters (Aksit et al., 1994a) present a synchronization filter,

Wait (Bergmans, 1994), capable of delaying message execution. The Wait filters specifi-

cation language separates synchronization from functionality, allows fine granularity

in synchronization constraints, and has high expressive power. Wait filters access a

set of abstract states which, despite modularity, are implemented using the functional

object’s variables. In addition, the Wait filters use of the functional object’s operation

100 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

names makes it impossible to define generic synchronization policies.

All of the previously mentioned approaches are language-based. Regarding class

libraries, there are few approaches handling object synchronization at the policy ab-

straction level: Karaorman & Bruno(1993), ABC++ (Arjormandi et al., 1995), the Active

Object pattern (Lavender & Schmidt, 1996), and Actalk (Briot, 1989).

Karaorman & Bruno, ABC++, and the Active Object pattern allow only the synchro-

nization given by the sequential object policy, i.e., invocations are stored in a queue

and afterwards selected for execution.

The Actalk object-oriented framework allows its customization for various

synchronization policies (Briot, 1996). Through the redefinition of the activi-

ty/synchronization component’s operations, Actalk supports policies using enabled

sets, guards, or both simultaneously. The problem with this approach is related to the

operations provided for customization. For instance, to define synchronization using

enabled sets it is necessary to extend the nextMessage operation, while to define syn-

chronization using guards it is also necessary to extend the nextMessage operation.

The combination of both extensions leads to mutual exclusion problems (Briot, 1996),

in the synchronization code, when trying to define a synchronization policy combining

enabled sets and guards. In the Synchronized Object pattern, this combination is solved

in a simple way, as mentioned in section 5.6.1.5. In addition, the Actalk framework

does not support optimist object synchronization policies.

5.8 Results

The Synchronized Object pattern describes a solution for object synchronization

which separates object synchronization from object functionality. This pattern has

high expressive power, concerning object synchronization policies and allows separate

reuse of object synchronization and functionality. In particular, it allows the definition

of generic synchronization policies which do not depend on the functional object’s in-

stance variables nor on its operation names, thus being usable by different functional

objects. The Synchronized Object pattern encapsulates synchronization within the func-

5.8. RESULTS 101

tional object, allowing, nevertheless, various object synchronization models. The pat-

tern is described using only basic object-oriented programming concepts. It can, thus,

be implemented using any object-oriented language.

The pattern was designed after an in-depth study of the state of the art and pos-

sesses unique qualities in the context of library-based approaches. In what concerns

language-based approaches, the pattern has the qualities of McHale’s proposal and,

in addition, allows the association of error conditions with synchronization and the

specialization of optimist object synchronization policies.

Silva(1996d) describes the Synchronized Object pattern using the format by Gam-

ma et al.(1994). It was afterwards described using the format used in this disserta-

tion (Silva, 1997a).

102 CHAPTER 5. SYNCHRONIZED OBJECT PATTERN

6Recoverable Object Pattern

The Recoverable Object pattern supports various object recovery policies. This de-

sign pattern separates the object recovery concern from object functionality.

6.1 Problem

Concurrent execution of two or more invocations on a object may result in an in-

consistent state. In this situation, it is necessary to update the object’s attributes with

the values they possessed in the last consistent state prior to the invocations. For in-

stance, if an object uses an optimist synchronization policy, which verifies consistency

only after an access has been carried out, it may be necessary to recover the object’s

state when an operation is aborted.

6.2 Analysis

Weihl(1993b) shows that all objects supporting recovery are built using one of two

object recovery policies:

� Update-In-Place. In update-in-place policies execution of an operation in an object

is immediate. In these policies, the object’s state always reflects the most recent

changes. Thus, from a recovery perspective, it is simple to confirm an invocation,

for the object’s state already contains the changes. However, if an invocation

aborts it is necessary to recover the object’s state to one prior to the aborted invo-

cation’s execution.

103

104 CHAPTER 6. RECOVERABLE OBJECT PATTERN

� Deferred-Update. In deferred-update policies an object is not changed until an op-

eration is confirmed. In these policies, an object’s state always reflects a consistent

state. Unconfirmed changes are stored elsewhere. Thus, in this case it is simple

to abort an invocation, for the object already has the state prior to the invocation.

However, if an invocation is confirmed it is necessary to update the object’s state

to account for the confirmed invocation.

Update-in-place policies optimize invocation confirmation while deferred-update

policies optimize invocation abortion.

In both policies, it is necessary to preserve enough information to allow recovery

or update of an object’s state: recovery on abort, in update-in-place policies; update on

confirm, in deferred-update policies. There are two ways of storing that information:

� Object Copy. Information is stored in an object copy. Recovery consists of re-

placing an object with its copy. In update-in-place policies, the copy contains

the consistent state prior to an invocation. In deferred-update policies, the copy

contains the state after an invocation, for it occurs in the object’s copy.

� Compensating Operations. There is a compensating operation associated with each

object operation. The compensating operation is capable of undoing an invoca-

tion. In update-in-place policies, the compensating operation undoes invocation

effects. In deferred-update policies, the compensating operation redoes invoca-

tion effects.

The option of using compensating operations or object copy should take into ac-

count the following tradeoffs: (i) object copy efficiency versus execution performance

of compensating operations; (ii) existence of an object copy operation in the program-

ming language versus customization capability of compensating operations.

6.3. FORCES 105

6.3 Forces

An object-oriented solution to the problem of object recovery considers the forces

mentioned in section 3.2.2:

� Expressiveness. The Recoverable Object pattern must support both policies:

update-in-place and deferred-update. In addition, it must allow invocation ef-

fects to be undone or redone using object copy or compensating operations.

� Modularity. The Recoverable Object pattern must separate object recovery from

object functionality. This separation is made difficult because the recovery policy

must be able to obtain and to change the functional object’s state. The functional

object must provide operations whose only goal is to allow either its copy or

compensating operations to change its state.

� Encapsulation. The Recoverable Object pattern must centralize the functional ob-

ject’s recovery. The responsibility should not be divided among its clients.

� Reusability. The Recoverable Object pattern must allow object recovery to be

reused by various functional objects. Object functionality and object recovery

must be separately extendible.

6.4 Structure and Participants

The class diagram presented in figure 6.1 illustrates the class structure of the Recov-

erable Object pattern.

The participants in the Recoverable Object pattern are:

� Client Object. Uses the functional object’s services.

� Functional Object. Contains the functionality. Depending on the object

recovery policy, it may be necessary to extend its interface with operations to be

used by Recovery Object instances.

106 CHAPTER 6. RECOVERABLE OBJECT PATTERN

Interface

m() m’()

ObjectFunctional

Recoverer

prepare()

ObjectClient

Recovery

Recovery

redo()undo()

prepare()redo()undo()

current

object

Object

Figure 6.1: Structure of the Recoverable Object pattern.

� Recovery Interface. It is responsible for intercepting Client Object in-

vocations to Functional Object associating them with an object recovery pol-

icy. Associates a Recovery Object instance with each invocation. Uses the

Recoverer’s services.

� Recoverer. It is responsible for recovering invocations. Association current

is used as an initial point from which invocations are undone or redone. Oper-

ations prepare, redo, and undo contain behavior, which is independent from

the functional object. It is responsible, respectively, for preparing invocation re-

covery, make effective invocation results, and undo invocation results.

� Recovery Object. Represents the invocation. Contains functional object-

specific information which allows it to prepare, redo, or undo an invocation. To

meet these responsibilities, operations prepare, redo, and undo may have to

use an extended interface of the Functional Object.

6.5 Collaborations

The sequence diagram presented in figure 6.2 illustrates the collaborations of the

Recoverable Object pattern.

6.5. COLLABORATIONS 107

m()

new()

Interfacea Recoverer

a Recovery

a Recovery

object = prepare()prepare(current)

m’()

redo()[COMMIT]

current = redo(current)

[ROLLBACK]undo()

current = undo(current)

ObjectFunctional

object

Object

CR

EA

TE

PRE

PAR

EFI

NIS

HE

XE

CU

TIO

N

Figure 6.2: Collaborations of the Recoverable Object pattern.

The diagram describes four collaboration phases:

� CREATE. When an operation is invoked on Recovery Interface, a Recov-

ery Object is created.

� PREPARE. This phase prepares an invocation’s recovery. It associates a Recov-

ery Object instance with it and obtains the objectwhere the invocation must

take place. During this phase, the Recovery Object instance must gather in-

formation necessary to future recovery actions.

� EXECUTION. In this phase, the invocation executes in the object returned by op-

eration prepare.

� FINISH. This phase takes place after the invocation’s execution in the object. Af-

ter this phase, object current has a consistent state. If the decision is to confirm,

through operation redo, then the current object has the state resulting from

executing the invocation associated with the Recovery Object instance. If the

decision is to abort, through operation undo, then the current object has the

108 CHAPTER 6. RECOVERABLE OBJECT PATTERN

state prior to executing the invocation associated with the Recovery Object

instance.

It should be noted that the decision to confirm or abort, in phase FINISH, is rep-

resented by the [COMMIT] and [ROLLBACK] conditions. The decision is made con-

sidering the invocation’s result or other events external to the invocation. This will be

discussed in section 6.6.3.

Finally, operations prepare, redo, and undo, of Recovery Object, trigger col-

laborations with the functional object to gather and recover its state. These collabora-

tions are not generic and, thus, are not represented in figure 6.2.

6.6 Forces Resolution

This section describes the way each of the forces presented in section 6.3 is solved.

6.6.1 Expressiveness

The Recoverable Object pattern supports the recovery policies identified during the

analysis phase.

The pattern’s expressiveness is achieved by specializing classes Recoverer

and Recovery Object. Recoverer specializations support update-in-place and

deferred-update policies, while Recovery Object specializations support object

copy and compensating operations.

6.6.1.1 Update-In-Place and Deferred-Update Policies

Update-in-place and deferred-update policies define a behavior independent from

the functional object to be recovered.

When specializing for the update-in-place policy, the current object always con-

tains the most recent updates. Thus, operation prepare of the Recoverer object re-

6.6. FORCES RESOLUTION 109

turns the current object to the Recovery Interface, where invocation execution

takes place. In this policy, operation redo of the Recoverer object does not perform

any action: the current object already contains the invocation results. In contrast,

operation undo of the Recoverer object must trigger the execution of the Recovery

Object’s undo operation to undo the effects of invocation execution on the current

object.

When specializing for the deferred-update policy, the current object contains the

state resulting from the most recently confirmed operation. Thus, operation prepare’s

return value depends on the return value of the Recovery Object’s prepare oper-

ation, and, thus, on the technique used: object copy or compensating operations. With

this policy, operation undo of the Recoverer object does not perform any action: the

current object is not changed by the invocation. In contrast, operation redo of the

Recoverer object must trigger the execution of the Recovery Object’s redo oper-

ation to update the current object with the invocation’s effects.

6.6.1.2 Object Copy and Compensating Operations

The implementation of the object copy and compensating operations techniques

should be adapted to the functional object.

The use of object copies to redo or undo invocation effects requires the specializa-

tion of class Recovery Object in order to copy the current object in its prepare

operation. Operations redo and undo return this copy. When the programming lan-

guage offers an object cloning operation, the only needed Recovery Object special-

ization defines the application of the object copy technique to any functional object.

The use of compensating operations to redo or undo invocation results requires

the specialization of class Recovery Object to implement compensating operations.

The Recovery Object’s redo and undo operations invoke operations on the cur-

rent object to, respectively, redo and undo the invocation’s results. The Recovery

Object’s prepare operation reads the current object’s state in order to gather in-

formation needed for recovery.

110 CHAPTER 6. RECOVERABLE OBJECT PATTERN

Special care is needed when using compensating operations together with

deferred-update policies. In this case, it is necessary for the Recovery Object’s

prepare operation to create an object copy so that the invocation is executed on it.

Nevertheless, a possible optimization consists of not executing the invocation if it does

not trigger invocations on other objects and does not return any values. This optimiza-

tions is supported if the Recovery Object’s prepare operation returns the NULL

object and class Recovery Interface does not trigger the EXECUTION phase un-

less object != NULL. In this case, it is not necessary to create a copy of the object.

The use of compensating operations requires the definition of a Recovery Ob-

ject subclass for each functional operation. In contrast, the use of object copy needs

a Recovery Object subclass to be defined for each functional class or, if allowed by

programming language, a single subclass of Recovery Object that can be applied

to any functional class.

6.6.2 Modularity

The Recoverable Object pattern separates object recovery from object functionality.

Object functionality is defined by the Functional Object, while object recovery is

defined by both the Recoverer and the Recovery Object. However, Recovery

Objects, which are responsible for recovery, may have to use an extended interface of

the Functional Object. The requirements on the Recovery Object’s part about

the functional object’s interface establish a dependence between functionality and re-

covery. The Recovery Interface object is responsible for integrating recovery and

functionality.

In should be noted that, if the Recovery Object uses object copy, modularity is

improved, for it only requires a duplication operation in each functional object. Mod-

ularity is completely achieved if the object model provides cloning operations. For

instance, all Smalltalk objects have a cloning operation.

6.6. FORCES RESOLUTION 111

6.6.3 Encapsulation

The Recoverable Object pattern centralizes recovery of functional object invocations.

The Recovery Interface object encapsulates recovery, thus hiding it from client

objects.

As in the previously presented patterns, encapsulation does not assume trans-

parency, where the client object ignores the existence of recovery. Depending on the

Recovery Interface’s definition, it is possible to have, or not, transparency. In or-

der not to have transparency it is enough for the Recovery Interface to allow a

client object to explicitly execute an invocation’s undo or redo.

The Recoverable Object pattern encapsulates the object recovery policy but not the

recovery model.

6.6.4 Reusability

The Recoverable Object pattern allows separate reuse of recovery and functionality

due to its modularity. Thus, the same functional object may be associated with vari-

ous recovery policies and these can be adapted for any functional object. Nevertheless,

customization requires Recovery Object subclasses to be defined as well as an ex-

tension to the functional object so that it provides the interface required by Recovery

Object instances. In the case of compensating operations, the functional object’s ex-

tension leads to the definition of Recovery Object subclasses for each of the new

functional operations as well as to the redefinition of Recovery Object subclasses

for the operations redefined due to the extension. In addition to the aforementioned

definitions and redefinitions of Recovery Object subclasses, it is necessary to ex-

tend the functional object’s interface with non-functional operations for recovery sup-

port.

112 CHAPTER 6. RECOVERABLE OBJECT PATTERN

6.7 Related Work

The need for invocation recovery is well known in the database and distributed

systems areas and several solutions have been presented (Bernstein & Goodman, 1987).

However, we are not aware of any class library-based approach offering a solution for

object recovery.

There are distributed systems which have object recovery, e.g. Argus (Liskov, 1988),

Arjuna (Shrivastava et al., 1991) and Hermes/ST (Fazzolare et al., 1994). Argus uses a

deferred-update policy with object copy but does not allow any customization. Arjuna

uses a update-in-place policy with object copy but does not allow any other policies. In

Hermes/ST only persistent objects may be recovered, through the use of a update-in-

place policy with attribute copy granularity: whenever an object’s attribute is changed,

its value is stored for later recovery.

6.8 Results

The Recoverable Object pattern describes a solution to object recovery which

separates object recovery from object functionality. This pattern allows the definition

of recoverable objects using update-in-place and deferred-update policies in conjunc-

tion with either the object copy or compensating operations state recovery techniques.

The patterns allows separate reuse of object recovery and object functionality, with the

restriction that Recovery Objects may need a specific functional object interface. In

particular, the Recoverer object defines generic recovery policies which may be used

by different functional objects. The Recoverable Object pattern encapsulates func-

tional object recovery allowing, nevertheless, different recovery models. The pattern

is described using only the basic object-oriented programming concepts and can, thus,

be implemented using any object-oriented language.

This pattern is the only solution known to the author to solve the problem of object

recovery.

Silva et al.(1997b) describes the Recoverable Object pattern.

Part III

Composition of Concerns

113

7Pattern Composition

In this chapter three composition patterns are described: Concurrent Synchronized

Object, Synchronized Recoverable Object, and Concurrent Synchronized Recoverable Object.

The composition of the Concurrent Object and Recoverable Object patterns is not consid-

ered, for, as mentioned in section 3.2.1, the object recovery concern is introduced in

the context of object synchronization policies. However, in a context where their com-

position is relevant, such as, for instance, redo/undo of actions on concurrent objects,

the corresponding composition pattern is defined in a similar way to the composition

patterns presented in this chapter.

The definition of composition patterns is non-trivial, for each of the participating

design pattern’s properties must be preserved in order to facilitate incremental devel-

opment. Thus, for instance, the expressiveness of each design pattern must be main-

tained in the composition pattern. In addition, the composition pattern must allow

design pattern customizations to be incrementally added.

7.1 Concurrent Synchronized Object Pattern

The Concurrent Synchronized Object pattern composes the Synchronized Object and

Concurrent Object patterns.

115

116 CHAPTER 7. PATTERN COMPOSITION

7.1.1 Problem

How to associate synchronization and concurrency with invocations to an object

so that synchronization and concurrency policies are combined.

7.1.2 Analysis

The composition of design patterns must consider two aspects: (i) new policies

introduced by the composition; (ii) restrictions that the composition pattern’s policies

impose on the combination of design pattern policies.

Two policies result from composing object synchronization and object concurrency,

depending on when the association of an activity with an invocation is carried out, i.e.,

whether it is done before the PRE-CONTROL phase or after it. The former is called

immediate association policy and the latter is called lazy association policy.

� In the immediate association policy, a functional object’s activity is immediate-

ly associated with invocation execution. Thus, this activity is also responsible

for executing the synchronization’s PRE-CONTROL phase. In this situation, the

client object’s activity returns immediately. The functional object’s activity also

executes the synchronization’s POST-CONTROL phase, being deassociated after

terminating that execution.

� In the lazy association policy, a functional object’s activity is associated with in-

vocation execution only after the synchronization’s PRE-CONTROL phase. In this

situation, it is the client object’s activity which executes the synchronization’s

PRE-CONTROL phase. The synchronization’s POST-CONTROL phase is executed

by the functional object’s activity, for the client object’s activity, in the case of the

sequential object and concurrent object policies, returns to execute in the client

object immediately before the synchronization’s EXECUTION phase.

It should be noted that the combination in which concurrency executes “nested” in

7.1. CONCURRENT SYNCHRONIZED OBJECT PATTERN 117

synchronization is not possible1, for there is no activity to execute the POST-CONTROL

phase. This combination would be similar to the lazy association, but activity deasso-

ciation would occur immediately after the synchronization’s EXECUTION phase.

The immediate association policy increases concurrency between client and func-

tional objects. On the other hand, the lazy association policy requires fewer resources,

for it creates new activities only when the invocation in fact executes in the functional

object, instead of creating activities which will be blocked or kept in busy wait in the

synchronization’s PRE-CONTROL phase. For instance, the use of immediate associa-

tion in an object with mutual exclusion synchronization, in which a single invocation

can execute at a time, needs several activities just to keep pending invocations in the

PRE-CONTROL phase.

The table shown in figure 7.1 presents restrictions imposed by composition pat-

tern policies on object concurrency policies. Object synchronization policies are not

restricted.

ObjectConcurrent Object

ConcurrentSynchronised Immediate Association Lazy Association

Non-Concurrent Object

Concurrent Object

Sequential Object

possible

possible

possible

impossible

impossible

possible

Figure 7.1: Conflict Matrix of the Synchronized Concurrent Object Pattern.

The advantage of the lazy association policy over the immediate association policy

is not apparent when objects are either non-concurrent or sequential, for in those cases

there is no creation of a new activity for each invocation. It is, thus, unnecessary to use

a lazy association policy with either non-concurrent or sequential object policies.

1In the immediate association policy, synchronization is executed “nested” in concurrency.

118 CHAPTER 7. PATTERN COMPOSITION

7.1.3 Forces

An object-oriented solution for the object concurrency and synchronization must

consider the forces mentioned in section 3.2.3:

� Expressiveness. The Concurrent Synchronized Object pattern must support the im-

mediate association and lazy association policies. In addition, the pattern must

preserve the expressiveness of both object synchronization and object concurren-

cy policies.

� Modularity. The Concurrent Synchronized Object pattern must separate object

synchronization and concurrency from object functionality. In addition, it must

maintain the separation between object synchronization and object concurrency.

� Encapsulation. The Concurrent Synchronized Object pattern must centralize the

functional object’s synchronization and concurrency.

� Reusability. The Concurrent Synchronized Object pattern must allow synchroniza-

tion, concurrency, and functionality to be independently reused and extended.

� Consistency. The Concurrent Synchronized Object pattern must consistently com-

pose the two design patterns avoiding inconsistent combinations.

7.1.4 Structure and Participants

The class diagram presented in figure 7.2 illustrates the class structure of the Con-

current Synchronized Object composition pattern. Dashed arrows represent the design

pattern where composition pattern classes come from. If a class is the destination of

more than one dashed arrow, this means that that class results from composing the de-

sign pattern classes at the origin of those arrows.2 To avoid unnecessary complications

in the figure, tags were applied only to dashed arrows associated with composition

2At this abstraction level of description, class composition corresponds to joining each of the isolatedclasses’ responsibilities. The concrete composition mechanism, from an object-oriented programminglanguage perspective, e.g. multiple inheritance or delegation, is, thus, irrelevant.

7.1. CONCURRENT SYNCHRONIZED OBJECT PATTERN 119

pattern classes which did not maintain the name they had in the corresponding design

pattern.

*

ClientObject

object

predicatesynchronization

method

Object

SynchronizedObject

Concurrent

Interface ObjectFunctional

concurrencyinterface

synchronizationinterface

execute()

Associator

Invocation

SynchronizerGenerator

DataSynchronization

Future

associate()

isError?()

finish()

invocations

Figure 7.2: Structure of the Concurrent Synchronized Object Pattern.

The participants in the Concurrent Synchronized Object pattern are:

� Client Object. Results from composing the two design patterns’ Client

Object classes, joining their responsibilities.

� Functional Object. Results from composing the two design patterns’

Functional Object classes.

� Interface. Results from composing the Synchronization Interface

and Concurrency Interface classes of the two design patterns. It is respon-

120 CHAPTER 7. PATTERN COMPOSITION

sible for intercepting invocations to Functional Object, delegating on Asso-

ciator the combination of object synchronization and object concurrency poli-

cies. It associates an Invocation object with each invocation.

� Invocation. Represents the invocation. Results from composing the Syn-

chronization Predicate and Method Object classes of the two design

patterns, joining their responsibilities. Unifies the invocation’s representation

responsibility common to both Synchronization Predicate and Method

Object. Operation finish is responsible for receiving the invocation’s termi-

nation status: either CONTINUE or ERROR.

� Associator. Is responsible for composing the object concurrency and objec-

t synchronization collaborations. Operation associate is responsible for the

composition’s first phase, in which an activity is associated with the invocation.

Operation execute is responsible for the composition’s second phase, in which

the invocation is executed. It uses the services provided by the Generator e

Synchronizer classes.

� Synchronizer, Synchronization Data. Result from theSynchronized Ob-

ject pattern’s classes with the same names.

� Generator, Future. Result from the Concurrent Object pattern’s classes with

the same names. Class Future is enriched with the isError? operation so

that the client object may know when the invocation has not executed due to a

synchronization error.

7.1.5 Collaborations

The collaborations between composition pattern participants are described in fig-

ure 7.3. The collaborations of each design pattern are integrated by class Associator.

When an operation is invoked, an Invocation is created and the composition’s

first phase is triggered in an Associator. In this phase, an Associator is respon-

sible for associating an activity with the invocation.

7.1. CONCURRENT SYNCHRONIZED OBJECT PATTERN 121

m()

new()

an Interface

an Invocation

execute()

execute()

execute()

an Associator

associate()

Figure 7.3: Collaborations of the Concurrent Synchronized Object Pattern.

When a Generator object invokes operation execute on an Interface, the

composition’s second phase is initiated in an Associator. The invocation is execut-

ed in this phase.

During both phases, an Associator triggers the object synchronization and con-

currency collaborations. It is also responsible for informing an Invocation about

the invocation’s termination status, by invoking operation finish with parameter

CONTINUE or ERROR. Immediately afterwards, an Invocationmust inform the Fu-

ture object about the termination status. This collaboration is not represented in fig-

ure 7.3.

7.1.6 Forces Resolution

The forces mentioned in section 7.1.3 are resolved by the Concurrent Synchronized

Object pattern.

122 CHAPTER 7. PATTERN COMPOSITION

7.1.6.1 Expressiveness

The Concurrent Synchronized Object pattern preserves the expressiveness of each

design pattern, for classes Generator, Method Object, Future, Synchronizer,

Synchronization Predicate and Synchronization Data are not changed by

the composition. They can, thus, be specialized in the same way they were in the

design pattern’s context. The restrictions in the matrix of figure 7.1 define the semantics

of composition policies but do not reduce each pattern’s expressiveness. It should be

noted that class Invocation composes Method Object and Synchronization

Predicate, orthogonally grouping the responsibilities of both classes, but without

changing them.

Communication variations expressed by class Concurrency Interface, of the

Concurrent Object pattern, are now the responsibility of the composition pattern’s

Interface class.

The Concurrent Synchronized Object pattern supports the immediate association and

lazy association policies through different specializations of class Associator.

Figure 7.4 shows the collaborations supporting the immediate association policy.

Class Immediate Associator, a subclass of Associator, supports the immediate

association policy. The PRE-CONTROL and POST-CONTROL blocks correspond to the

phases with the same names in the collaborations of the Synchronized Object pattern.

The PRE-CONTROL block is executed after an activity has been associated with the

invocation.

Figure 7.5 shows the collaborations supporting the lazy association policy. Class

Lazy Associator, a subclass of Associator, supports the lazy association policy.

The PRE-CONTROL block is executed before an activity has been associated with the

invocation.

7.1.6.2 Modularity

In a way similar to that of design patterns, the Concurrent Synchronized Object pat-

tern separates object functionality from object synchronization and concurrency, for

7.1. CONCURRENT SYNCHRONIZED OBJECT PATTERN 123

an Invocation

execute()

a Generatoran Interface

start()

execute()

PRE-CONTROL

POST-CONTROL

[xStatus=CONTINUE]execute()

finish()

new()m()

Associatoran Immediate

associate()

Figure 7.4: Collaborations of the Concurrent Synchronized Object Pattern: immediateassociation.

class Functional Object defines the functionality, being the remaining concerns

defined in other classes.

Regarding the separation between synchronization and concurrency, classes In-

terface and Invocation are the only which result from composing design pattern

classes and, thus, the only where modularity may be compromised.3

Class Interface preserves the separation between concurrency and synchroniza-

tion, for it delegates on class Associator the composition of object concurrency col-

laborations and object synchronization collaborations. Moreover, the two specializa-

tions of class Associator restrict themselves to invoking the interfaces of the Gen-

erator and Synchronizer classes.

3Actually, classes Client Object and Functional Object also result from composing designpattern classes, but they have the same responsibilities in both design patterns, making their composi-tion idempotent.

124 CHAPTER 7. PATTERN COMPOSITION

a Generatoran Interface

finish()

new()m()

an Invocation

execute()

POST-CONTROL

finish()

execute()

PRE-CONTROL

start()[xStatus=CONTINUE]

execute()

Associatora Lazy

associate()

Figure 7.5: Collaborations of the Concurrent Synchronized Object Pattern: lazy associa-tion.

Class Invocation unifies the responsibility of invocation representation and ag-

gregates the remaining responsibilities of classes Method Object and Synchro-

nization Predicate. It should be noted that classes Method Object and Syn-

chronization Predicate have in common the responsibility of invocation repre-

sentation. However, operation finish mixes concurrency and synchronization, since

the propagation of synchronization errors to the Future object is the composition’s

new responsibility, involving the enrichment of the previous responsibilities of class

Method Object. Nevertheless, this modularity loss does not affect the way the spe-

cializations of Method Object are defined, for the new responsibility does not need

to be specialized for each customization. This means that the loss of modularity in the

composition does not reflect itself in the customizations for each policy. That is, inde-

pendent reuse of concurrency and synchronization, one of the most important conse-

quences of modularity, is preserved.

7.2. SYNCHRONIZED RECOVERABLE OBJECT PATTERN 125

7.1.6.3 Encapsulation

The Concurrent Synchronized Object pattern centralizes the functional object’s syn-

chronization and concurrency. The Interface object hides object synchronization

and object concurrency from client objects.

It should be noted that encapsulation does not assume transparency. The Future

object’s operation isError? allows the client object to know whether synchronization

errors have occurred.

7.1.6.4 Reusability

The Concurrent Synchronized Object pattern allows separate reuse of synchroniza-

tion, concurrency, and functionality due both to its modularity and to the reusability

property of each of the participating design patterns. Also, the Associator objects

may be reused in different functional objects.

7.1.6.5 Consistency

Class Associator subclasses consistently compose the collaborations of the two

design patterns. The restrictions the composition pattern’s policies impose on the ob-

ject concurrency policies, indicated in the matrix shown in figure 7.1, are supported

neither by the structure nor by the collaborations of the Synchronized Concurrent Ob-

ject pattern. These restrictions must be guaranteed by the object-oriented framework

which implements the composition pattern, as will be seen in chapter 9.

7.2 Synchronized Recoverable Object Pattern

The Synchronized Recoverable Object pattern composes the Synchronized Object and

Recoverable Object patterns.

126 CHAPTER 7. PATTERN COMPOSITION

7.2.1 Problem

How to synchronize invocations to an object, allowing recovery of the object to its

state prior to the invocation.

7.2.2 Analysis

Object recovery is necessary only when an invocation successfully passes the syn-

chronization’s PRE-CONTROL phase, for only in that case does it execute on the func-

tional object. Thus, there is only one way of composing object synchronization and

object recovery: recovery must prepare the functional object for recovery after the syn-

chronization’s PRE-CONTROL phase and must recover the object after the synchroniza-

tion’s POST-CONTROL phase. This is the only policy which must be supported by the

composition pattern.

Another relevant aspect of this composition is related to the need for executing re-

covery code in mutual exclusion, in the same way synchronization code is executed in

mutual exclusion. Concurrent execution of recovery code, by several activities, might

corrupt the structures manipulated during recovery.

This composition pattern’s policy does not restrict, in any way, the policies of the

participating design patterns. However, it can be shown that recovery policies have

impact on synchronization policies. For instance, consider the synchronization and re-

covery of a Buffer class, possessing get and first operations, the latter returning,

without changing the object, the item that would be removed by the get operation.

The conflict relation between these two operations is different depending on whether

the Buffer’s recovery policy is update-in-place or deferred-update. In the case of an

update-in-place policy, simultaneous execution of the two operations may generate er-

ror situations, for they manipulate the same internal object variables. However, in the

case of a deferred-update policy, the object’s state is not corrupted by the simultane-

ous execution of both operations, since each execution occurs in a different copy of the

Buffer object. In this case, the simultaneous execution corresponds to a sequential

execution of the two operations: first ; get.

7.2. SYNCHRONIZED RECOVERABLE OBJECT PATTERN 127

It should be noted that the dependency relation between object synchronization

and object recovery policies occurs at the level of the specializations of the policies

specific to the functional object: classes Synchronization Predicate, Synchro-

nization Data and Object Recovery. However, there are no restrictions to com-

binations of specializations of policies independent from the functional object: classes

Synchronizer and Recoverer.

A last aspect to be considered in this composition is the problem of synchroniza-

tion information recovery. However, this problem has already been solved by the Syn-

chronized Object pattern. This pattern considers the possibility of invocation abort. It

provides the abort operation in class Synchronization Predicate, which is re-

sponsible for recovering the synchronization’s state.

7.2.3 Forces

An object-oriented solution to the problem of object synchronization and recovery

must consider the forces mentioned in section 3.2.3. The forces, except for expressive-

ness, are formulated in a similar way to the forces of the Concurrent Synchronized Object

pattern.

The expressiveness force for the Synchronized Recoverable Object pattern requires

the composition pattern to preserve the expressiveness of object synchronization and

object recovery policies.

7.2.4 Structure and Participants

The class diagram presented in figure 7.6 illustrates the class structure of the Syn-

chronized Recoverable Object pattern.

The participants in the Synchronized Recoverable Object pattern are:

� Client Object. Results from composing the Client Object classes of the

two design patterns, joining their responsibilities.

128 CHAPTER 7. PATTERN COMPOSITION

Invocation

invocations*

ClientObject Object

FunctionalInterface

predicatesynchronization

SynchronizerRecoverer

ObjectRecoverable

ObjectSynchronized

synchronizationinterface

recoveryobject

interfacerecovery

DataSynchronization

Figure 7.6: Structure of the Synchronized Recoverable Object Pattern.

� Functional Object. Results from composing the Functional Object

classes of the two design patterns.

� Interface. Results from composing the Synchronization Interface

and Recovery Interface classes of the two design patterns. It is responsible

for intercepting invocations to Functional Object and for associating them

with synchronization and recovery policies. It associates an Invocation object

with each invocation.

� Invocation. Represents the invocation. It results from composing the Syn-

chronization Predicate and Recovery Object classes of the two design

patterns, joining their responsibilities. Unifies invocation representation respon-

sibility, common to both Synchronization Predicate and Recovery Ob-

ject.

� Synchronizer, Synchronization Data. Result from the Synchronized Ob-

ject pattern’s classes with the same names.

7.2. SYNCHRONIZED RECOVERABLE OBJECT PATTERN 129

� Recoverer. Results from the Recoverable Object pattern’s class with the same

name.

7.2.5 Collaborations

The collaborations between the composition pattern’s participants are described in

figure 7.7. Since there is only one policy in the composition pattern, collaborations of

each design pattern are integrated by the Interface class. The PRE-CONTROL and

POST-CONTROL blocks correspond to the phases with the same names in collabora-

tions of the Synchronized Object pattern.

m()

new()

ObjectFunctional

object

an Invocation

an Interface a Recoverer

PRE-CONTROL

[xStatus=CONTINUE]object = prepare()

prepare(current)

m’()

redo()[xStatus=CONTINUE]

current = redo(current)

[xStatus=ERROR]undo()

current = undo(current)

POST-CONTROL

Figure 7.7: Collaborations of the Synchronized Recoverable Object Pattern.

When an operation is invoked, an Invocation is created. After the PRE-

CONTROL phase, if the invocation can continue executing, the object where the in-

130 CHAPTER 7. PATTERN COMPOSITION

vocation is to be executed is obtained. The value returned by the POST-CONTROL

determines whether recovery must proceed to redo or undo the invocation results, re-

spectively, using the redo and undo operations.

The f PRE-CONTROL ; prepare g and f POST-CONTROL ; (redo | un-

do) g sequences must execute in mutual exclusion, for their concurrent execution

would result in corruption of synchronization and recovery information. This mutual

exclusion is not represented in figure 7.7.

7.2.6 Forces Resolution

Forces are solved as in the Concurrent Synchronized Object composition pattern. On-

ly the resolution of the consistency force requires special care.

The structures and collaborations of the Synchronized Recoverable Object pattern do

not forbid any combination of object synchronization and recovery policies, for they

depend only on the functional object, as mentioned in the Analysis section. These

restrictions may be guaranteed by the object-oriented framework which implements

the composition pattern whenever predefined policies are used.

7.3 Concurrent Synchronized Recoverable Object Pattern.

The Concurrent Synchronized Recoverable Object pattern composes the Concurrent Ob-

ject, Synchronized Object, and Recoverable Object patterns.

7.3.1 Problem

How to synchronize and to associate concurrency with invocations to an object

while allowing object invocation recovery.

7.3. CONCURRENT SYNCHRONIZED RECOVERABLE OBJECT PATTERN. 131

7.3.2 Analysis

To identify the new policies introduced by the composition pattern, object syn-

chronization and recovery are considered first. As in section 7.2.2, it can be concluded

that there is only one consistent combination of synchronization and recovery: recov-

ery must prepare the functional object after the synchronization’s PRE-CONTROLphase

and must recover the object, committing or aborting, after the synchronization’s POST-

CONTROL phase.

Regarding the combination with object concurrency, the two policies identified in

section 7.1.2 must be considered: Immediate association, in which an activity is im-

mediately associated with an invocation’s execution, and lazy association, in which an

activity is associated with an invocation just before it is to be executed on the functional

object. In addition to these two policies, there is a combination in which the associa-

tion occurs after the synchronization’s PRE-CONTROL phase and before the function-

al object is prepared for recovery. However, this combination is very similar to the

lazy association policy, for it is only in the synchronization’s PRE-CONTROL phase that

activities are blocked or remain in busy wait. Thus, the composition pattern is not re-

quired to support this combination. In addition, it should be noted that, for the reasons

mentioned in section 7.1.2, the deassociation of an activity must always occur after ex-

ecution of the synchronization’s POST-CONTROL and the recovery’s FINISH phases.

The restrictions the composition pattern imposes on object concurrency policies

are the same imposed by the Concurrent Synchronized Object pattern, represented in the

matrix shown in figure 7.1. As in the Synchronized Recoverable Object pattern, recovery

policies have impact on the definition of synchronization conflicts between operations.

7.3.3 Forces

An object-oriented solution to the problem of object concurrency, synchronization

and recovery must consider the forces mentioned in section 3.2.3. The forces are for-

mulated as for the Concurrent Synchronized Object e Synchronized Recoverable Object com-

position patterns, but now dealing with the composition of the three design patterns.

132 CHAPTER 7. PATTERN COMPOSITION

7.3.4 Structure e Participants

The class diagram presented in figure 7.8 illustrates the class structure of the Con-

current Synchronized Recoverable Object composition pattern. For the sake of readability,

the design patterns where each of the composition pattern’s classes originates are not

shown.

DataSynchronization

Generator

Recoverer

Invocation

Future

ClientObject Interface Object

Functional

Synchronizer

Associator

associate()execute()

isError?()

setObject()finish()

invocations*

Figure 7.8: Structure of the the Concurrent Synchronized Recoverable Object Pattern.

The participants in the Concurrent Synchronized Recoverable Object pattern are:

� Client Object. Results from composing the Client Object classes of the

three design patterns, joining their responsibilities.

� Functional Object. Results from composing the Functional Object

classes of the three design patterns.

7.3. CONCURRENT SYNCHRONIZED RECOVERABLE OBJECT PATTERN. 133

� Interface. Results from composing the Synchronization Interface,

Recovery Interface, and Concurrency Interface classes of the three

design patterns. It is responsible for intercepting invocations to Functional

Object, delegating on Associator the responsibility of combining object syn-

chronization, recovery, and concurrency policies. It associates an Invocation

object with each invocation.

� Invocation. Represents an invocation. Results from composing the Syn-

chronization Predicate, Recovery Object, and Method Object of the

three design patterns, joining their responsibilities. Unifies the responsibility for

invocation representation, common to Synchronization Predicate, Re-

covery Object, and Method Object. Two new operations, finish and se-

tObject, are defined to integrate, respectively, object synchronization and con-

currency, and object recovery and concurrency. Operation finish is responsible

for receiving the invocation’s termination status: either CONTINUE or ERROR.

Operation setObject is responsible for defining the functional object where the

invocation is to take place.

� Associator. Is responsible for composing the collaborations of object concur-

rency, synchronization, and recovery. Operation associate is responsible for

the composition’s first phase, in which an activity is associated with an invoca-

tion. Operation execute is responsible for the composition’s second phase, in

which the invocation is executed. It uses the services of the Generator, Syn-

chronizer, and Recoverer classes.

� Synchronizer, Synchronization Data. Result from the classes with the

same names of the Synchronized Object pattern.

� Recoverer. Results from the class with the same name of the Recoverable Object

pattern.

� Generator, Future. Result from the classes with the same names of the Con-

current Object pattern. Class Future is enriched with operation isError? so

that the client object may be able to know if the invocation was not executed due

to a synchronization error.

134 CHAPTER 7. PATTERN COMPOSITION

7.3.5 Collaborations

The collaborations between the composition pattern’s participants are divided into

two phases.

In the first phase, the Interface object creates a new instance of class Invoca-

tion and invokes class Associator’s associate operation in order to associate an

activity with the invocation. Depending on the policy, operation associate may also

trigger the execution of both the synchronization’s PRE-CONTROL and the recovery’s

PREPARE phases.

In the second phase, when the Interface object receives an execute invocation

from a Generator object, it invokes class Associator’s execute operation. This

operation is responsible for triggering both the execution on the functional object and

the execution of both the synchronization’s POST-CONTROL and the recovery’s FIN-

ISH phases. Depending on the policy, operation execute may also trigger the execu-

tion of both the synchronization’s PRE-CONTROL and the recovery’s PREPARE phases

before executing the invocation.

Whenever an invocation finishes, in any phase, the Associator object informs the

Invocation object about the invocation’s termination status, by invoking the fin-

ish operation, parameterized with CONTINUE or ERROR. Immediately afterwards, the

Invocation object informs the Future object about the termination status.

The f PRE-CONTROL ; PREPARE g and f POST-CONTROL ; FINISH g se-

quences must be executed in mutual exclusion, since their concurrent execution would

result in the corruption of both the synchronization and the recovery information.

7.3.6 Forces Resolution

The forces mentioned section 7.3.3 are solved by the Concurrent Synchronized Recov-

erable Object pattern in a way similar to that of the previously presented composition

patterns. Only the expressiveness and modularity forces require special care.

7.3. CONCURRENT SYNCHRONIZED RECOVERABLE OBJECT PATTERN. 135

7.3.6.1 Expressiveness

The Concurrent Synchronized Recoverable Object pattern supports the immediate as-

sociation and lazy association policies through different specializations of the Asso-

ciator class.

Figure 7.9 shows collaborations for the immediate association policy. Class Imme-

diate Associator, a subclass of Associator, supports the immediate association

policy.

The PRE-CONTROL and POST-CONTROL blocks correspond to the phases with the

same names of the Synchronized Object pattern. The integration of these two synchro-

nization phases and recovery is identical to that of the Synchronized Recoverable Object

pattern. However, it is necessary to use the setObject operation to integrate object

recovery and concurrency, for the object on which Method Object performs invo-

cations may vary as a result of recovery. Operation setObject defines, for each in-

vocation, the functional object, returned by the Recoverer’s prepare operation, on

which execution is to be triggered. Operation setObject invokes an identical opera-

tion on the Method Object (not shown). The integration with the object concurrency

collaborations is also similar to that of the immediate association policy, carried out in

the Concurrent Synchronized Object pattern.

Figure 7.10 shows the collaborations for the lazy association policy. The integra-

tion of the two synchronization phases with recovery is identical to the one described

for immediate association policies. The integration with concurrency collaborations is

similar to the integration carried out for the lazy association policy of the Concurrent

Synchronized Object pattern.

7.3.6.2 Modularity

Class Invocation’s finish and setObject operations need clarification.

Operation finish mixes concurrency and synchronization, since the propagation

of synchronization errors to the Future object is the composition’s new responsibility,

involving the enrichment of previous Method Object responsibilities.

136 CHAPTER 7. PATTERN COMPOSITION

start()

execute()

a Generator a Recoverer

an Invocation

m()

new()

an Interface

associate()

execute()

PRE-CONTROL

[xStatus=CONTINUE]object = prepare()

POST-CONTROL

[xStatus=CONTINUE]redo()

undo()[xStatus=ERROR]

execute()

setObject(object)

prepare(current)

current = redo(current)

current = undo(current)

finish()

an ImmediateAssociator

Figure 7.9: Collaborations of the Concurrent Synchronized Recoverable Object Pattern:immediate association.

7.3. CONCURRENT SYNCHRONIZED RECOVERABLE OBJECT PATTERN. 137

m()

new()

an Interface a Generator a Recoverer

an Invocation

associate()

PRE-CONTROL

[xStatus=CONTINUE]object = prepare()

start()[xStatus=CONTINUE]

setObject(object)

prepare(current)

execute()

POST-CONTROL

[xStatus=CONTINUE]redo()

finish()

undo()[xStatus=ERROR]

execute()

current = redo(current)

current = undo(current)

execute()

a LazyAssociator

Figure 7.10: Collaborations of the Concurrent Synchronized Recoverable Object Pattern:lazy association.

138 CHAPTER 7. PATTERN COMPOSITION

Operation setObject mixes object recovery and object concurrency, for the first

determines the functional object to be invoked, while performing the invocation on the

functional object is the Method Object’s responsibility. That is, the composition has

a new responsibility involving the enrichment of previous responsibilities of Method

Object.

As in the case of the Concurrent Synchronized Object pattern, modularity loss does

not affect the way Method Object specializations are defined. Independent reuse of

concurrency, synchronization, and recovery, one of the most important consequences

of modularity, is preserved.

7.4 Related Work

To the extent of the author’s knowledge, little work exists on the composition of

these three concerns. The reasons for this are, as mentioned in the previous chapters,

either that recovery has not been considered, or that, frequently, concurrency does not

appear separate from synchronization. For instance, in Mediators (Grass & Campbel-

l, 1986), synchronization and concurrency are coded together, thus preventing sepa-

rate reuse of synchronization and concurrency. Actalk (Briot, 1996) also joins synchro-

nization and concurrency in the same activity/synchronization component. Moreover,

Briot(1996) affirms, in the future work section, that he considers difficult separating a

complex concern, such as the one supported by the activity/synchronization compo-

nent, into completely orthogonal parts.

In spite of there existing little work on composing these three concerns, the prob-

lems and solutions presented in this chapter allow the analysis of other approaches

considering separation and composition of concerns.

Aspect-oriented programming (Kicsales et al., 1997) uses the aspect weaver to au-

tomatically compose different aspects. It has been seen, in this chapter, that several

composition policies may exist, being the programmer’s responsible for choosing one

of them. Using aspect-oriented programming, it will be necessary, in this context, to

define a language capable of expressing the several composition policies: a language

7.5. RESULTS 139

capable of composing aspect languages. This language is not considered, to the ex-

tent of our knowledge, by aspect-oriented programming approaches. In addition, the

relationship between these composition languages and the aspect weaver is not clear.

Composition filters (Aksit et al., 1994a) are sequentially composed and the com-

position semantics is given by the logical operators: AND, if a message has to pass

through both filters; and OR, if a message needs only to pass through one of them. It

has been seen in this chapter that consistent compositions are not necessarily sequen-

tial or nested compositions. This leads to the representation of each concern by several

filters, to allow non-sequential and non-nested compositions. In this way, the goal of

having a filter for each concern is not accomplished. The solution becomes closer to

the fragmentation present in the CodA approach (McAffer, 1995), with the complexity

problems already mentioned in section 3.3.3.

Finally, it should be emphasized that the impact of recovery policies on the defi-

nition of synchronization policies, mentioned in section 7.2.2, was also identified by

Weihl(1993a) in the context of transactions.

7.5 Results

This chapter presented the compositions of three design patterns associated with

object synchronization, concurrency, and recovery concerns. We are not aware of any

other work handling these compositions. The compositions have been described as

composition patterns, which consistently integrate design patterns and preserve their

properties. In addition, it has been shown that composition may lead to several consis-

tent combinations, called composition policies. The composition pattern must express

these policies. These observations call into question the feasibility of approaches using

automatic composition of concerns (Kicsales et al., 1997) or their sequential compo-

sition (Aksit et al., 1994a). Composition patterns are described using only the basic

concepts of the object-oriented paradigm and can, thus, be implemented using any

object-oriented language.

The composition of design patterns to describe object-oriented frameworks has

140 CHAPTER 7. PATTERN COMPOSITION

been presented by Silva et al.(1999). Silva(1998) discusses the problems presented in

this chapter, using the composition of the Synchronized Object and the Active Objec-

t (Lavender & Schmidt, 1996) patterns. As has already been mentioned, the Active

Object pattern corresponds to the sequential object policy of the Concurrent Object pat-

tern.

8Pattern Language

The pattern language describes the activities associated with an incremental devel-

opment process in which concurrency introduction is delayed in order to allow debug-

ging and testing of application functionality in a non-concurrent and, thus, determin-

istic environment.

8.1 Introduction

This section introduces the pattern language and an example which will be used to

illustrate the pattern language’s application to a concrete concurrent program.

8.1.1 Process Patterns

The pattern language consists of two process patterns:

� The Functionality Pattern indicates how a sequential version of the program can

be built emphasizing functional aspects and so that concurrency can be incre-

mentally introduced afterwards.

� The Concurrency Pattern indicates how to incrementally enrich a sequential pro-

gram with concurrency.

Obviously, these two process patterns do not define a complete development pro-

cess, but the activities they describe must be part of any development process where

concurrency is to be incrementally introduced.

141

142 CHAPTER 8. PATTERN LANGUAGE

As mentioned in section 3.2.4, the format used to describe process patterns consist-

s of the following items: Problem, Context, Forces, Strategy, Resulting Context, and

Example.

8.1.2 Administrator Program

To illustrate the pattern language’s application the Administrator program, previ-

ously described by Papathomas(1995), is used.

Figure 8.1 presents the functional entities which intervene in the Administrator ex-

ample program.

WORKERSCLIENTS

WORKLOAD MANAGER

ADMINISTRATOR

Figure 8.1: Administrator Program.

The Administrator program has the following features:

1. Several CLIENTS exist which make requests to the ADMINISTRATOR, obtaining

the request’s results.

2. The ADMINISTRATOR concurrently accepts requests from different CLIENTS, de-

composing each request into subrequests which are sent to WORKERS.

3. The ADMINISTRATOR may trigger concurrent execution of a request’s subre-

quests if these correspond to tasks which may be executed in parallel.

8.2. FUNCTIONALITY PATTERN 143

4. The ADMINISTRATOR triggers a request’s execution only if all necessary WORK-

ERS for executing all subrequests exist. Otherwise, the ADMINISTRATOR returns

an error to the CLIENT responsible for the request.

5. The WORKLOAD MANAGER maintains information on the WORKERS state and on

requests pending execution.

6. WORKERS are responsible for executing subrequests and sending the results to

the ADMINISTRATOR which computes the final result and returns it to the corre-

sponding CLIENT.

7. WORKERS register themselves with the ADMINISTRATOR at creation time.

8. The time WORKERS takes to execute a subrequest varies according to subrequest

type.

These features define both the functional and the non-functional requirements of

the Administrator program’s architecture. In particular, the program’s functional

and non-functional requirements are those in its frontier entities.

The frontier of the Administrator program is defined by the ADMINISTRATOR.

CLIENTS are the program’s users. Thus, the model presented to the program’s user-

s is given by the ADMINISTRATOR’s interface. According to the features described

above, this is a transparency model for object concurrency, for CLIENTS wait for each

request’s end before resuming execution. From the object synchronization perspec-

tive, this is a non-transparency model, for CLIENTS receive an error when there are

not enough WORKERS for executing subrequests.

8.2 Functionality Pattern

This activity builds a program which implements the desired functionalities. This

program is tested and debugged in a deterministic environment.

144 CHAPTER 8. PATTERN LANGUAGE

8.2.1 Problem

How to validate functional requirements without implementing the whole pro-

gram and, in particular, without implementing concurrency?

8.2.2 Context

A problem specification already exists. That specification includes non-functional

requirements associated with objects such as, for instance, the existence of simultane-

ous activities.

Two non-functional requirement types associated with objects are considered: ex-

plicit and implicit. Explicit non-functional requirements are those which are apparent

in the object’s interface, such as, for example, the return of a future object. Implicit

non-functional requirements may be encapsulated by the object’s interface, such as,

for example, the association of activities with invocation execution to improve perfor-

mance.

In should be noted that the non-functional requirements in the program’s interface

define the program’s model to the user. In the context of the Administrator program,

the model is given by the non-functional requirements, implicit and explicit, of the

only entity in the frontier with the user: the ADMINISTRATOR.

8.2.3 Forces

To validate the program’s requirements, the user has to, from the very early stages,

be able to evaluate the execution of program parts.

However, satisfaction of all requirements, both functional and non-functional, in-

creases the program’s complexity and, consequently, development time. Thus, it will

be faster to develop a sequential version which ignores non-functional requirements

and which allows concurrency to be incrementally introduced at a later time.

8.2. FUNCTIONALITY PATTERN 145

Nevertheless, incremental concurrency introduction is not possible without chang-

ing the interfaces of the sequential version’s classes due to the explicit non-functional

requirements. Concurrency introduction leads to a change of model: the model cannot

be encapsulated by object interfaces, as discussed in sections 4.6.3, 5.6.3, and 6.6.3.

8.2.4 Strategy

The strategy consists of developing a sequential version satisfying the functional

and explicit non-functional requirements.

Explicit non-functional requirements must be satisfied using design and compo-

sition patterns associated, respectively, with concerns and composition of concerns.

However, application of these patterns must, in this phase, use only “non-concurrent

policies”, so that the program is deterministic.

For example, futures may be implemented using synchronous invocations; the

Concurrent Object pattern does not associate a new activity for executing an in-

vocation. Another example is given by synchronization based on object state, which

must return an error whenever invocations request unavailable resources.

8.2.5 Resulting Context

Satisfaction of functional requirements results from applying the strategy. The ex-

plicit non-functional requirements for which the “non-concurrent policies” are suffi-

cient, such as synchronization based on object state, are satisfied.

From the user’s perspective, the relevant non-functional requirements are those

in the program’s interface, i.e., the ones which define the model. Thus, due to the

non-concurrent implementation, the user may perceive a program which does not sat-

isfy the explicit non-functional requirements which are associated with the program’s

interface and which require “concurrent policies”, such as asynchronous invocations.

Moreover, the satisfaction of implicit non-functional requirements is perceivable by the

user only through collateral effects on performance.

146 CHAPTER 8. PATTERN LANGUAGE

A program’s functionalities may be tested and debugged in a sequential environ-

ment. Customizations of each concern are delayed. It is possible to evaluate the se-

quential version to decide where concurrency introduction is necessary.

8.2.6 Example

The architecture of the Administrator program has both explicit and implicit non-

functional requirements. Concurrent request acceptance by the ADMINISTRATOR is an

implicit requirement, for CLIENTS wait for the request’s termination to resume exe-

cution. The ADMINISTRATOR’s ability to trigger concurrent execution of subrequests

is an explicit non-functional requirement. This requirement leads to the definition of

WORKERS which return a future object with a subrequest’s result. The fact that the

ADMINISTRATOR triggers the execution only if there are enough WORKERS for the ex-

ecution of subrequests is another explicit non-functional requirement. From this re-

quirement results the definition of the ADMINISTRATOR’s interface to return an error

to the CLIENTS.

Firgure 8.2 presents a class diagram belonging to the sequential version of the Ad-

ministrator program. Dashed arrows indicate that the pattern where the arrow starts is

applied to the class at the arrow’s end. Dashed classes denote external entities which

interact with the program.

Administrator

ObjectSynchronized

Client Worker*

ConcurrentObject

Figure 8.2: Administrator Program: Class Diagram for the Sequential Version.

The sequential version has three functional classes, Client, Administrator,

8.3. CONCURRENCY PATTERN 147

and Worker, which satisfy the functional requirements: to make requests, to decom-

pose requests and return results, and to execute subrequests. Class Client is a proxy

for the external entities which are integrated in the program.

The non-concurrent satisfaction of explicit non-functional requirements is achieved

by applying the Synchronized Object pattern to class Administrator and by applying

the Concurrent Object pattern to class Worker.

The synchronized Administrator class integrates the WORKLOAD MANAGER’s re-

sponsibilities, thus satisfying the requirement that an error should be returned if a par-

ticular Worker does not exist. Whenever a Worker object is created, it must register

itself with the Administrator, triggering the change of synchronization information

within the Synchronization Data object of the Synchronized Object pattern.

The concurrent Worker class allows the Administrator object to trigger con-

current execution of subrequests. The Administrator object receives a future for

each subrequest. In the sequential version, concurrent Worker objects use the non-

concurrent object policy.

The sequential version satisfies the user’s model, for the only explicit non-

functional requirement belonging to the program’s interface is satisfied by a “non-

concurrent” synchronization policy, based on information about workers availability.

8.3 Concurrency Pattern

This activity enriches the program developed in the previous activity with con-

currency. Design patterns must be incrementally introduced delaying introduction of

concerns and policies responsible for non-determinism.

8.3.1 Problem

How is object concurrency introduced in the sequential program in a flexible and

incremental way, and transparently to client classes?

148 CHAPTER 8. PATTERN LANGUAGE

8.3.2 Context

A sequential version of the program supporting the functionalities was implement-

ed and tested. However, non-functional requirements were either not implement-

ed (implicit requirements) or implemented using non-concurrent policies (explicit re-

quirements).

The satisfaction of the implicit non-functional requirements leads to the creation

of internal activities encapsulated by the object, and to the synchronization of accesses

to an object which is accessed simultaneously by various activities in order to prevent

corruption of its state. Objects which are simultaneously accessed by various activities

are said to be shared.

The introduction of the object concurrency concern is complex and may originate

errors which are hard to debug. For instance, it is difficult to debug a sequential object,

for the scheduling of invocations to be executed, done by the internal activity, is hard

to reproduce.

8.3.3 Forces

Given the complexity resulting from concurrency introduction, it is important to

allow an incremental development in which, starting with the sequential version, it

is only necessary to add concurrency code without changing code already developed.

Moreover, concurrency introduction should be incremental as well, and it should allow

testing and evaluation of several policies, to help choosing the customization which

better satisfies the non-functional requirements.

The flexibility associated with testing and evaluation of various policies, required

by incremental development, is based on the properties of design patterns: expressive-

ness, modularity, encapsulation, and reusability.

Nevertheless, flexibility requires the programmer to fully understand the complex-

ity associated with each design pattern, with special emphasis on expressiveness1.

1It should be noted that the programmer will also have to understand the complexity associated with

8.3. CONCURRENCY PATTERN 149

Reuse of predefined policies provides simplicity, from the programmers point of view,

since it reduces the complexity associated with each concern. However, it also reduces

flexibility.

8.3.4 Strategy

The strategy consists of enriching the sequential version of the program with con-

currency, both through the replacement of non-concurrent policies with concurrent

policies, in order to satisfy explicit non-functional requirements, and through the in-

troduction of design patterns, in order to satisfy implicit non-functional requirements.

In order to delay introduction of non-determinism and to simplify concurrency

introduction, the following two criteria are suggested:

� Delay object concurrency introduction by introducing concurrency to a class at a

time.

� Use predefined policies first and customize them later.

The first criterion suggests that the program’s concurrency “quantity” be con-

trolled. It must be also possible to remove concurrency from an already tested object,

so that it can participate in the testing of other objects as a non-concurrent object.

The second criterion suggests that a program be enriched with predefined poli-

cies in such a way as to allow simple concurrency introduction. For instance, the use

of the mutual exclusion policy for synchronizing all shared objects allows tests to be

carried out quickly, in a concurrent environment, delaying policy customization, such

as replacement of the mutual exclusion policy with readers/writers policies. Mutual

exclusion policies also reduce interleaving and, thus, non-determinism.

Given the impact recovery policies have on synchronization policies, as mentioned

in section 7.2, object recovery should be introduced only during object synchronization

customization.

integration mechanisms to be able to replace policies.

150 CHAPTER 8. PATTERN LANGUAGE

The use of a sequential object policy may also simplify synchronization, for se-

quential objects are intrinsically mutual exclusion objects and, thus, do not need the

application of the Synchronized Object pattern to avoid the state corruption scenarios

that result from concurrent accesses.

8.3.5 Resulting Context

Design patterns associated with each concern are incrementally introduced allow-

ing incremental testing and debugging.

The program was enriched with concurrency using object synchronization, recov-

ery, and concurrency policies. Since concurrency introduction was done incrementally,

it was possible to evaluate various policies, as well as do customizations according

to the program’s concrete needs. If policy customization is unnecessary, concurrency

introduction is simple, for the programmer is able to use predefined policies.

The incremental introduction of design patterns and the incremental customization

of policies allow test procedures to be flexible:

� Test object concurrency without needing to customize object synchronization

policies based on invocation state. For instance, by using mutual exclusion poli-

cies to all shared objects.

� Incrementally test program concurrency, by incrementally introducing object

concurrency, i.e., one class at a time.

8.3.6 Example

Concurrency introduction in the sequential version of the Administrator program

must satisfy both the implicit and the explicit non-functional requirements.

Figure 8.3 presents the class diagram corresponding to the final version of the Ad-

ministrator program. The development of this version was carried out according to the

criteria defined in the strategy item.

8.3. CONCURRENCY PATTERN 151

AdministratorClient

Worker 1

Worker 2

Worker 3

ObjectSynchronizedConcurrent

*

*

*

SynchronizedObject

ConcurrentObject

ConcurrentSynchronizedRecoverable

Object

ConcurrentObject

Figure 8.3: Administrator Program: Class Diagram (Concurrent Version).

The implicit requirement that the Administrator concurrently accepts requests

is satisfied by the existence of several Client objects to which the Concurrent Object

pattern was applied. The Client objects may use a sequential object policy to guar-

antee that each client only makes one request at a time and waits for its termination.

The Administrator concurrently accepts Client requests. The customization of the

Synchronized Object pattern, applied to class Administrator, is changed to manage

concurrent access to Worker objects. Synchronization should consider the availability

of workers and their sharing constraints. In particular, the Administrator’s syn-

chronization may be changed, when a particular Worker is unavailable, to delay the

invocation, instead of returning an error to the Client object2.

2When the Administrator no longer returns an error, the error handling code on the client side,developed in the sequential version, will never be executed. However, another possible synchronizationwould be a timeout event, returning an error, if after a given wait period the particular Worker has notbeen created.

152 CHAPTER 8. PATTERN LANGUAGE

The customization of the Concurrent Object pattern, applied to class Worker, is

changed so that it uses object concurrency policies such as sequential object and con-

current object. Depending on execution time and on subrequest type, different object

concurrency policies may be used. It should be noted that the non-concurrent object

policy may be the most appropriate if execution time is short.

In addition to the Administrator’s responsibility in the synchronization of

Worker objects, the Synchronized Concurrent Object may be applied to some of the

Worker classes if additional synchronization is deemed necessary. The preferable so-

lution is assigning to the Administrator the responsibility for synchronization in

terms of semantics/specification of Worker classes. Furthermore, each Worker class

is responsible for the synchronization required by its implementation.

Finally, the Recoverable Synchronized Concurrent Object pattern should be applied to

the Worker classes when required by the synchronization’s customization.

8.4 Related Work

The development process definition is part of the object-oriented analysis and de-

sign methods (Rumbaugh et al., 1991; Jacobson, 1992; Shlaer & J.Mellor, 1992; Bergman-

s, 1994; Booch, 1994; Coleman et al., 1994; Selic et al., 1994; Low et al., 1996; Rasmussen

et al., 1996b; Rasmussen et al., 1996a; Booch et al., 1998). As mentioned in section 2.5.3,

the gap between analysis and design models in some of these methods (Rumbaugh

et al., 1991; Jacobson, 1992; Booch, 1994; Coleman et al., 1994; Low et al., 1996; Ras-

mussen et al., 1996b; Rasmussen et al., 1996a; Booch et al., 1998) causes the incremental

development achieved in analysis models to be lost when they are transformed into

design models. Other methods (Shlaer & J.Mellor, 1992; Selic et al., 1994; Bergmans,

1994) which propose automatic generation of programs from analysis models present

efficiency problems.

Methods for the development of concurrent programs from sequential ones (Car-

omel, 1993; Karaorman & Bruno, 1993) do not present the gap between analysis and

design, for they have constructs which support the concurrency and synchronization

8.4. RELATED WORK 153

concerns at the programming language abstraction level.

The development process described by Caromel(1993) consists of the following

steps:

1. Sequential Programming and Design: in which a sequential program is developed.

2. Process Identification: in which sequential program classes, which must be en-

riched with internal activities, are identified. Among those classes are the classes

of objects which either continuously control a resource or are shared (need to be

synchronized).

3. Process Programming: in which classes that were enriched with an internal activity

are changed to support synchronization. This change from synchronous to asyn-

chronous invocation is transparently carried out by the compiler using future

objects.

4. Adaptation to Constraints: in which the program is customized in order to satisfy

real-time requirements.

According to these steps, it is clear that object synchronization is jointly introduced

with object concurrency, for all shared objects must have an internal activity. In addi-

tion, the transparent way in which future objects are introduced allows, in principle,

client objects to remain unchanged. However, transparency may lead to client object

inefficiency. For instance, if the Administrator class were to be unaware of the fact

that Worker objects are concurrent, it would be unable to interleave periodic subre-

quest termination verification with other processing. The main reason for this is that

Caromel considers all non-functional requirements as implicit and, thus, the only sup-

ported concurrency model is a transparent one.

Karaorman & Bruno(1993) also propose a development process in which, immedi-

ately after developing the sequential program, “active” objects are identified. In this

way, separate introduction of object synchronization is avoided. Furthermore, clients

of classes enriched with object concurrency must be changed so they can use an asyn-

chronous interface with future objects.

154 CHAPTER 8. PATTERN LANGUAGE

The G++ pattern language (Aarsten et al., 1995; Aarsten, 1997) describes a develop-

ment process of client-server programs for CIM architectures. This language suggests

the enrichment of objects with concurrency but does not consider the use of “non-

concurrent” policies to allow incremental testing and debugging.

8.5 Results

The pattern language described in this chapter supports an incremental develop-

ment of concurrent programs which solves the conflict between reuse and incremental

development through the identification of implicit and explicit non-functional require-

ments, as well as through the use of “non-concurrent” policies of design patterns.

Other results achieved through the pattern language are:

� Validation of Functional Requirements. The pattern language allows rapid de-

velopment of object functionality, allowing the validation of functional require-

ments.

� Flexibility. Since it is impossible to find an optimal policy for all cases, a solu-

tion must be customized for each situation. The pattern language allows policies

to be chosen taking into account both the semantics and the operations of ob-

jects. Moreover, it is possible to replace policies without propagating changes to

functionality code.

� Simplicity. When it is unnecessary to customize policies, the use of predefined

policies allows the programmer to remain unaware of the complexity inherent to

each concern’s solution.

The pattern language was published by Silva(1997b).

9Object-oriented

Framework

Design and composition patterns are implemented by an object-oriented frame-

work. This framework guarantees the properties of these patterns and simplifies their

use by the final programmer. The properties responsible for this simplification are

guaranteed by the three-layered architecture with separation of concerns, which is, in

addition, implementation environment independent. The object-oriented framework

presented in this chapter follows such an architecture. This framework has been coded

using the C++ programming language and the abstract concurrency and synchroniza-

tion mechanisms provided by the ACE library.

9.1 Architecture

Inconsistent specialization and combinatorial explosion are two problems usually

attributed to object-oriented frameworks (Ruping, 1996). Inconsistent specialization is

a consequence of the flexibility offered by frameworks, which allows some inconsis-

tent combinations of class specializations. Combinatorial explosion happens because

a class’ specialization frequently requires the specialization of many others. These two

problems make it difficult for programmers to use the framework.

To avoid these problems, the object-oriented framework we propose follows a

three-layered architecture with separation of concerns, which simplifies its use by the

programmers. The architecture hides from programmers the complexity associated

with pattern composition and, in addition, allows incremental customization of poli-

cies associated with each design pattern. This architecture reduces the possibility of

155

156 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

inconsistent specialization, for class specializations for pattern composition are not the

framework users’ responsibility and class specializations for customization of each de-

sign pattern are, as much as possible, independent from each other. This architecture

also reduces the combinatorial explosion, for the composition and customization unit

is the component.1

Figure 9.1 again presents the component diagram illustrating the object-oriented

framework’s architecture. As has already been seen, the relations between components

are composition, integration, and customization, and the three layers considered in the

object-oriented framework are concern, composition, and application.

CONCERNLAYER

COMPOSITIONLAYER

APPLICATIONLAYER

CONCERN B

COMPOSITION X COMPOSITION Y

CONCERN A

CLASS C1 CLASS C2

compositionconcern

compositionconcern

compositionconcern

CONCERN A CONCERNS A,B

componentintegration

PROGRAM customizationpolicy

customizationpolicy

customizationpolicy

componentintegration

Figure 9.1: Three-layered Architecture with Separation of Concerns.

Each concern consists of components, called concern components, which imple-

ment the design patterns associated with concerns. In the composition layer, concern

components are combined into composition components. Finally, in the application

layer, composition components are integrated with the application’s functional object-

s, and concern components are customized to support the concern policies required

by functional objects. It should be noted that, since composition patterns may possess

1Components were defined in section 3.2.5.

9.1. ARCHITECTURE 157

their own composition policies (see section 7.1.2), composition components may also

have to be customized in the application layer.

Concern and composition components must guarantee the properties, respectively,

of design and composition patterns. In addition, the architecture defines the properties

each layer must possess in order to simplify its use. These properties, summarized

here, have been previously mentioned in section 3.2.5:

� Concern Layer. Concern components must possess classes to ease their com-

position in the composition layer and the customization of their policies in the

application layer.

� Composition Layer. Composition components must possess a minimal interface

in order to reduce integration work in the application layer. This interface en-

capsulates pattern composition, reducing the number of methods and classes the

application layer programmer must be aware of to be able to use composition

components. Singular compositions of concern components, such as Composi-

tion X in figure 9.1, are necessary to give the corresponding concern component

a minimal interface.

� Application Layer. Integration and customization in the application layer of

components from upper layers must have the properties of both transparent in-

tegration and incremental customization. Integration of composition components in

the application layer, done using the minimal interface, must be as transparent

as possible, in the sense that changing functional objects and their clients should

be unnecessary. Customization of concern and composition components should

be done incrementally, by reusing previous customizations, in order to allow in-

cremental introduction of concerns, and corresponding customizations, in the

application’s functional objects.

The architecture’s properties have the following impact on the implementation of

concern and composition components:

� Concern components do not implement some of the classes described by the

design pattern and introduce new classes, not described by the design pattern.

158 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

Client Object and Functional Object classes, defined in all design pat-

terns, are only defined in the application layer by the final programmer. New

classes are introduced, either to ease the composition of concern components in

the composition layer, or to allow the incremental customization in the applica-

tion layer. Other classes may also be introduced, either to take advantage from

the implementation language’s specificities, such as C++’s template classes, or to

provide concurrency and synchronization mechanisms.

� Composition components introduce classes which compose concern compo-

nents and define the minimal interfaces. As in concern components, Client

Object and Functional Object classes, participants in composition pattern-

s, are not part of composition components.

9.2 Object Concurrency, Synchronization and Recovery

Figure 9.2 presents the concern and composition components, part of the object-

oriented framework, for object concurrency, synchronization, and recovery. In addition

to the three concern components, the figure presents the composition components for

the singular composition of object concurrency and synchronization concern compo-

nents, as well as the composition components for the composition patterns described

in chapter 7.

In the following sections the structure of some of these components is presented.

9.2.1 Concern Layer

The presentation of concern components describes each component’s classes em-

phasizing the features which allow its composition and customization in following

layers.

The concern layer consists of the three concern components shown in fig-

ure 9.2: CONCURRENT OBJECT, SYNCHRONIZED OBJECT, and RECOVERABLE OB-

JECT. These components have a set of common aspects:

9.2. OBJECT CONCURRENCY, SYNCHRONIZATION AND RECOVERY 159

COMPOSIÇÃOCAMADA

CAMADAFACETA

COMPOSITIONCONCURRENT

OBJECTSYNCHRONIZEDCONCURRENT

COMPOSITION

OBJECT

CONCURRENTSYNCHRONIZEDRECOVERABLE

OBJECT

COMPOSITIONSYNCHRONIZEDCOMPOSITION

RECOVERABLEOBJECT

SYNCHRONIZEDCOMPOSITION

OBJECT

SYNCHRONIZEDOBJECT

RECOVERABLEOBJECT

CONCURRENTOBJECT

Figure 9.2: Framework for Object Concurrency, Synchronization, and Recovery.

� In order to ease composition, it is necessary to define a new class in each concern

component, respectively, Concurrent Invocation, Synchronized Invo-

cation, and Recoverable Invocation. These new classes represent an in-

vocation. The composition of these classes allows the unification of invocation

representations in design patterns. Invocations are represented in design patterns

by classes Method Object, Synchronization Predicate, and Recovery

Object.

� Concern components use the ACE Thread, ACE Thread Semaphore,

ACE Condition Thread Mutex, ACE Thread Mutex, and

ACE Recursive Thread Mutex ACE library classes as concurrency and

synchronization mechanisms.

� The Client Object and Functional Object classes, of design patterns, are

not part of concern components and must be defined in the application layer by

the framework’s user.

160 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

INVOCATIONINVOCATION

Interface{abstract}

generatorType

status{abstract}{abstract}

execute()finish()delConcInvocation()

ConcurrentObject

Method{abstract}

Future

validerror

available()isAvailable?()isError?()

Thread_MutexACE_Condition

finish()execute()

Concurrency

Invocation

OBJECT

MethodObject_O

{abstract}

OBJECT object

setObject()

ACE_ThreadMutex

Future_T

TYPE

TYPE value

getValue()putValue()

{abstract}

generatorType

Generator

delGenerator()

deleted?

Generator GeneratorSequentialConcurrentNonConcurrentGenerator

ACE_ThreadSemaphoreACE_Thread

Queue

ExclusionMutual

Figure 9.3: Concern Layer: CONCURRENT OBJECT Component.

9.2. OBJECT CONCURRENCY, SYNCHRONIZATION AND RECOVERY 161

9.2.1.1 Concurrency Concern

Figure 9.3 presents the CONCURRENT OBJECT component whose classes we de-

scribe below:

� Concurrency Interface. Defines an abstract interface which will be used

in component composition. Its generatorType instance variable indicates the

object concurrency policy.

� Concurrent Invocation. This class factors the invariant responsibilities of

all Method Object customizations and contains an instance of Method Ob-

ject. Concurrent Invocation’s delConcInvocation method is invoked

to inform that the Concurrent Invocation object is no longer needed from

the object concurrency perspective. The other methods of class Concurren-

t Invocation delegate on the Method Object the methods which have the

same names.

� Generator. Generator subclasses implement the three object concurrency

policies of the Concurrent Object pattern. Class ACE Thread is used by both Con-

current Generator and Sequential Generator to create activities. Class-

es ACE Thread Semaphore and Mutual Exclusion are used by Sequen-

tial Generator for synchronization.

� Queue. Template class Queue implements the invocations association, in fig-

ure 4.4, between Sequential Generator and Method Object. The INVO-

CATION parameter will be instantiated in each composition with a class repre-

senting the invocation in that composition.

� Method Object, Method Object O, Future, and Future T. These are the

customization classes to be specialized in the application layer. In particular, Fu-

ture is enriched in order to ease composition with the SYNCHRONIZED OBJECT

component; Future T is a template class of futures which return values of type

TYPE; and Method Object O is defined in order to ease composition with the

RECOVERABLE OBJECT component.

162 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

This component solves both the synchronization problems associated with Se-

quential Generator objects and the composition problems associated with the

SYNCHRONIZED OBJECT and RECOVERABLE OBJECT components, as shown below.

In what concerns synchronization, class Generator is enriched with the delGen-

eratormethod in order to synchronize the client object’s activity in charge of destroy-

ing Sequential Generator instances with its internal activity, for the Queue object

may only be destroyed after the internal activity has finished. Otherwise, the internal

activity could try to access the Queue object after its destruction by the client objec-

t. To implement the delGenerator method, class Sequential Generator has

an ACE Thread Semaphore object to block the client object’s activity. In addition,

to implement the mutual exclusion mentioned in section 4.6.1.1, class Sequential

Generator has a Mutual Exclusion object which defines the mutual exclusion be-

tween insertion of new invocations on the Queue object, by the client object’s activity,

and the choice of a new invocation to be executed, by the internal activity.

To allow compositions with the SYNCHRONIZED OBJECT component, class Fu-

ture is enriched with the isError? method. This enrichment must be done in this

layer, for it is necessary in two different compositions and is also needed to allow in-

cremental customization in the application layer. Method isError? returns an error

when an invocation cannot occur due to a synchronization error. For the same reason,

class Method Object is also enriched with the finish method in order to receive

the termination state of a synchronized invocation: either CONTINUE or ERROR. The

introduction of these two methods implements the solution for the modularity prob-

lem mentioned in sections 7.1.6.2 and 7.3.6.2.

To allow compositions with the RECOVERABLE OBJECT component, class Method

Object O is defined. This class is introduced in this component, instead of be-

ing inserted into the corresponding composition components, to allow incremental

customization in the application layer. Using specializations of Method Object O,

instead of those of Method Object, it is possible to incrementally introduce cus-

tomizations of the RECOVERABLE OBJECT component without it being necessary to

change previous customizations done to the CONCURRENT OBJECT component. Class

9.2. OBJECT CONCURRENCY, SYNCHRONIZATION AND RECOVERY 163

Method Object O implements the solution to the modularity problem mentioned in

section 7.3.6.2.

9.2.1.2 Synchronization Concern

InterfaceSynchronization SynchronizerContext

Concurrency

status

require()preGuard()postGuard()pre()exec()post()commit()abort()delSyncInvocation()

{abstract}

{abstract}

{abstract}{abstract}

{abstract}Predicate_T

Synchronization

{abstract}

{abstract}

SynchronizedInvocation

SynchronizerPessimistic

SynchronizerOptimistic

DataSynchronization

SynchronizationPredicate

INVOCATIONINVOCATION

Queue

ConcurrencyContext

Passive

Thread_MutexACE_Condition ACE_Thread

Mutex

ConcurrencyContext

Active

delay()awake()loop?()

Figure 9.4: Concern Layer: SYNCHRONIZED OBJECT Component.

Figure 9.4 presents the SYNCHRONIZED OBJECT component, whose classes are

described next:

� Synchronization Interface. Defines an abstract interface which will be

used in component composition.

� Synchronized Invocation. This class factors the invariant responsibilities of

164 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

all Synchronization Predicate customizations and contains a Synchro-

nization Predicate instance. This class has a composition support purpose

similar to that of class Concurrent Invocation of the CONCURRENT OBJECT

component.

� Synchronizer. Its subclasses implement the pessimist and optimist policies of

the Synchronized Object pattern.

� Queue. A template class, Queue implements the invocations association be-

tween Synchronization Predicate objects. The INVOCATION parameter is

instantiated in each composition with a class representing the invocation in that

composition.

� Synchronization Predicate T and Synchronization Data. These are

customization classes to be specialized in the application layer. Synchroniza-

tion Predicate T is a template class with parameter INVOCATION, for the

Queue argument type is composition-dependent.

� Synchronization Predicate. This class avoids propagation of template

classes to the other component classes.

� Concurrency Context. This class and its two subclasses are defined to ease

composition with the CONCURRENT OBJECT component.

There is a consistency problem when implementing the composition of synchro-

nization and concurrency. The synchronization PRE-CONTROL and POST-CONTROL

phases may have to delay invocation execution and invocation termination. The way

this delay is implemented depends on the object concurrency policy. If it is a sequen-

tial object policy, delaying an invocation corresponds to moving it to the end of the

pending invocations queue. Otherwise, if it is either a non-concurrent or a concurrent

object policy, delaying an invocation corresponds to blocking its activity. It should be

noted that blocking an activity of a sequential object results in a deadlock situation.

To solve this problem, the SYNCHRONIZED OBJECT component defines two Concur-

rency Context subclasses to permit the consistent composition with the CONCUR-

RENT OBJECT component. Class Active Concurrency Context must be used in

9.2. OBJECT CONCURRENCY, SYNCHRONIZATION AND RECOVERY 165

the composition with the sequential object policy, for its implementation of method

delay does not block the activity. Class Passive Concurrency Context must be

used in the compositions with the other policies, for its implementation of method

delay blocks the activity.

9.2.1.3 Recovery Concern

Figure 9.5 presents classes which are part of the RECOVERABLE OBJECT compo-

nent.

OBJECT OBJECT

OBJECTOBJECT

OBJECTOBJECT

Interface{abstract}{abstract}

Recovery Recoverer

OBJECT object OBJECT current

UpdateDeferred

Placein

Update

{abstract}

status

{abstract}Invocation

prepare()redo()undo()delRecInvocation()

RecoverableObject

Recovery

Figure 9.5: Concern Layer: RECOVERABLE OBJECT Component.

The component’s class definition strategy is similar to that of the two previously

presented components. Nevertheless, in this component, all classes are template class-

es. Their parameter is OBJECT, which represents the functional object. The OBJECT

parameter is the argument or return value of the methods of component classes, e.g.

prepare and undo. This parameter will be instantiated only in the application layer.

It should be noted that in the other two concern components it was not necessary to

define an OBJECT parameter.

166 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

9.2.2 Composition Layer

The presentation of composition components emphasizes the definition of their

minimal interface and the support to consistent concern composition.

The composition layer consists of the five composition components shown in fig-

ure 9.2. These components have a set of common aspects:

� The composition, using inheritance, of classes Concurrency Interface,

Synchronization Interface, and Recovery Interface composes the

collaborations of the design patterns and defines the minimal interface to be used

in the application layer.

� The composition, using inheritance, of classes Concurrent Invocation,

Synchronized Invocation, and Recoverable Invocation unifies invo-

cation representation and manages its destruction. The invocation object’s de-

struction is policy-dependent, for an invocation’s termination does not necessar-

ily imply the corresponding object’s destruction. For instance, a given synchro-

nization policy may need to use information on committed invocations in order

to synchronize other invocations. Thus, it is necessary that all policies, of each of

the concerns involved in the composition, agree on the invocation’s destruction.

� In each composition, the template class Queue is instantiated with a class result-

ing from composing invocation classes.

In order to simplify the description of the minimal interface, the class diagrams

presented in this section are enriched with a prefix character which indicates whether

a method is private (-) or protected (#). Public methods are not prefixed. All attributes

are either private or protected.

In the following subsections the COMPOSITION SYNCHRONIZED OBJECT and

COMPOSITION CONCURRENT SYNCHRONIZED OBJECT components are presented.

The other composition components are not shown since they are defined in a simi-

lar way and do not present different problems. In the code examples, the names of

9.2. OBJECT CONCURRENCY, SYNCHRONIZATION AND RECOVERY 167

classes, methods, and attributes have been slightly changed in order to reduce their

dimension.

9.2.2.1 Synchronized Object Composition

<SynchronizedQueue

Composition>Invocation

#createInvocation()#preControl()#postControl()

InterfaceSynchronization

{abstract}

SynchronizedInvocation

{abstract}

SynchronizedInvocation

Composition

delSyncInvocation()

SynchronizationInterface

{abstract}

#~Synchronized...()

Composition

ExclusionMutual

lock()unlock()

Thread_MutexACE_Recursive

Figure 9.6: Composition Layer: COMPOSITION SYNCHRONIZED OBJECTComponen-t.

Figure 9.6 presents the classes which are part of the COMPOSITION SYNCHRO-

NIZED OBJECT component:

� Synchronization Interface Composition. Extends the Synchroniza-

tion Interface class by defining the minimal interface and guaranteeing the

components consistency.

� Synchronized Invocation Composition. Extends the Synchronized

Invocation class by redefining method delSyncInvocation.

� Queue. Results from instantiating template class Queue with this composition’s

invocation type: class Synchronized Invocation Composition.

� Mutual Exclusion. This class is used in order to support the mutual exclusion

associated with the execution of synchronized code, as mentioned in section 5.5.

168 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

The component’s minimal interface is defined in class Synchronization In-

terface Composition by protected methods createInvocation, preControl,

and postControl. This interface’s use will be exemplified in section 9.2.3.

The following code fragments show how classes Synchronization Inter-

face Composition and Synchronized Invocation Composition guarantee

the component’s consistency.

To solve the problem of composition consistency, mentioned in section 9.2.1.2, the

constructor of class Synchronization Interface Composition must create an

instance of a subclass of Concurrency Context. In this composition, an instance

of Passive Concurrency Context is created, for invocations are executed by the

client object’s activity and, to delay the invocation, it is necessary to block that activity.

The constructor of class Synchronization Interface Composition, presented

in figure 9.7, is, in addition, responsible for creating objects from classes Synchro-

nizer, Mutual Exclusion, and Queue. The latter must be instantiated by the invo-

cation’s composition class: Synchronized Invocation Composition.

Synchronization_Interface_CMP::Synchronization_Interface_CMP(Synchronizer::Sync_Type syncType)

{// synchronizer creation: pessimistic or optimisticif (syncType == Synchronizer::PESSIMISTIC)synchronizer_ = new Pess_Synchronizer();

else if (syncType == Synchronizer::OPTIMISTIC)synchronizer_ = new Opt_Synchronizer();

// concurrent context creationconcContext_ = new Passive_Conc_Context();

// mutual exclusion object creationmutualExclusion_ = new MutualExclusion();

// queue creationqueue_ = new Queue<Synchronized_Invocation_CMP>();

}

Figure 9.7: Synchronization Interface Composition Class: Constructor.

The implementation of mutual exclusion, associated with the execution of synchro-

nization code of the Synchronized Object pattern, must be carried out in the composition

layer, for, as can be seen in chapter 7, it varies according to the composition. The pre-

Control method of class Synchronization Interface Composition, present-

9.2. OBJECT CONCURRENCY, SYNCHRONIZATION AND RECOVERY 169

ed in figure 9.8, implements mutual exclusion in the PRE-CONTROL phase by using

the lock and unlock methods. In addition, it should be noted that busy wait is not

used, for the preControl method of the Synchronization Interface Compo-

sition blocks the activity if the result of the PRE-CONTROL phase is DELAY. Method

postControl has a structure similar to that of preControl, but in this case, blocked

activities are reactivated if the result of the POST-CONTROL phase is other than DELAY.

Execution_Status Synchronization_Interface_CMP::preControl(Synchronized_Invocation_CMP* invocation){

Execution_Status xStatus;

// pre-controldo {// begin mutual exclusionmutualExclusion_->lock();

// verify compatibilityxStatus = synchronizer_->preControl(invocation);

// end mutual exclusionmutualExclusion_->unlock();

// if there are incompatibility waitif (xStatus == DELAY)

concContext_->delay(invocation);}while (xStatus == DELAY);

// return resultreturn xStatus;

}

Figure 9.8: Synchronization Interface Composition Class: preControl.

In order to consistently compose the various invocation representations, method

delSyncInvocation of class Synchronized Invocation Composition is re-

defined as shown in figure 9.9. In this composition, where only synchronization is

present, when the object synchronization policy no longer needs the invocation infor-

mation, the corresponding Synchronized Invocation Composition object may

be effectively destroyed.

9.2.2.2 Concurrent Synchronized Object Composition

Figure 9.10 presents the classes the COMPOSITION CONCURRENT SYNCHRONIZED

OBJECT component consists of:

170 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

void Synchronized_Invocation_CMP::delSyncInvocation(){

// the synchronized invocation is deleteddelete this;

}

Figure 9.9: Synchronized Invocation Composition Class: delSyncInvoca-tion.

� Concurrency Synchronization Interface Composition. Extends, us-

ing multiple inheritance, classes Concurrency Interface and Synchro-

nization Interface. Defines the minimal interface and guarantees the com-

ponent’s consistency.

� Concurrent Synchronized Invocation Composition. Extends, using

multiple inheritance, classes Concurrent Invocation and Synchronized

Invocation. Redefines methods delConcInvocation and delSyncInvo-

cation.

� Queue. Results from instantiating template class Queue with this composition’s

invocation type: class Concurrent Synchronized Invocation Composi-

tion.

� Mutual Exclusion. Is used to support the mutual exclusion associated with

the execution of both the synchronization code and the access by the Sequen-

tial Generator object to the Queue object. This is done because the synchro-

nization code also accesses the Queue object.

� Concurrency Synchronization Associator. This class’ subclasses sup-

port the association policies of the Concurrent Synchronized Object pattern. pre-

Control and postControl are private auxiliary methods used by method-

s associate and execute of Concurrency Synchronization Associa-

tor subclasses to execute, respectively, the PRE-CONTROL and POST-CONTROL

phases shown in the diagrams of figures 7.4 and 7.5.

The component’s minimal interface is defined in class Concurrency Synchro-

nization Interface Composition by protected method createInvocation.

9.2. OBJECT CONCURRENCY, SYNCHRONIZATION AND RECOVERY 171

delConcInvocation()

{abstract}CompositionInterface

delSyncInvocation()#~ConcurrentSync...()

SynchronizedInvocation

Composition

InterfaceSynchronization

{abstract}

SynchronizationConcurrency Concurrent

#createInvocation()execute()

ConcurrencySynchronization

Associator{abstract}

AssociatorSynchronization

Concurrency

AssociatorSynchronization

ConcurrencyImmediate Lazy Concurrency

Context{abstract}

Queue<ConcurrentSynchronizedInvocationComposition>

associate()execute()-preControl()-postControl()

Interface{abstract}

ConcurrencyInvocation

{abstract}

Concurrent SynchronizedInvocation

{abstract}

MutualExclusion

Synchronizer{abstract}

Generator{abstract}

Figure 9.10: Composition Layer: COMPOSITION CONCURRENT SYNCHRONIZED OB-JECT Component.

This interface’s use will be exemplified in section 9.2.3.

The following code fragments show how classes Concurrency Synchroniza-

tion Interface Composition, Concurrency Synchronization Associa-

tor, and Concurrent Synchronized Invocation Composition guarantee the

component’s consistency.

The constructor of class Concurrency Synchronization Interface Com-

position, of which a fragment is shown in figure 9.11, has the responsibility of solv-

ing the problem mentioned in section 9.2.1.2. Thus, it can be seen that if the objec-

t concurrency policy is sequential object, then a instance of Active Concurrency

Context is created, since the internal activity cannot be blocked when method delay

is executed. It can also be seen how the constructor guarantees consistency according

to the conflicts matrix, in figure 7.1, for the lazy association policy can only be com-

bined with the concurrent object policy.

172 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

Concurrent_Synchronization_Interface_CMP::Concurrent_Synchronization_Interface_CMP(Conc_Sync_Associator::Assoc_Type assocType,

Generator::Gen_Type genType,Synchronizer::Sync_Type syncType)

: Conc_Inter(genType),associator_(0),queue_(0)

{queue_ = new Queue<Concurrent_Synchronized_Invocation_CMP>();

mutualExclusion_ = new MutualExclusion();

// creation of generator and concurrency context...

else if (genType == Generator::SEQUENTIAL){// creates sequential generatorgenerator_ = new Sequential_Generator<Conc_Sync_Inv_CMP>(this, queue_);

// active concurrent context creationconcContext_ = new Active_Conc_Context();

}

...

// synchronizer creation...

// associator creation...

else if (assocType == Conc_Sync_Associator::LAZY){// treats incompatible combination of association and concurrency policiesif (genType == Generator::CONCURRENT)

// creates lazy associatorassociator_ = new Lazy_Conc_Sync_Associator(generator_, concContext_, synchronizer_,

queue_, mutualExclusion_);else{

cout<<"WARNING: INCOMPATIBLE COMBINATION OF POLICIES!!"<<endl;

// creates immediate associatorassociator_ = new Immediate_Conc_Sync_Associator(generator_, concContext_, synchroniz-

er_,queue_, mutualExclusion_);

}}

}

Figure 9.11: Concurrency Synchronization Interface Composition Class:Constructor (fragment).

9.2. OBJECT CONCURRENCY, SYNCHRONIZATION AND RECOVERY 173

In this composition, the consistent implementation of mutual exclusion, associated

with the execution of synchronization code, must include the invocation of method

finish, when the synchronization returns an error. Figure 9.12 presents the imple-

mentation of mutual exclusion in the preControl method of Concurrency Syn-

chronization Associator, using the lock and unlock methods. Regarding the

method with the same name in the SYNCHRONIZED OBJECT component, it should

be noted that the while guard uses the loop? method of the concContext object.

Thus, the guard depends on the object concurrency policy. In the case of the sequen-

tial object policy, the loop? method, when invoked with argument DELAY, returns

TRUE because method delay puts the invocation at the end of the pending invoca-

tions queue and the internal activity is responsible for recurrently executing pending

invocations. In the case of non-concurrent and concurrent object policies, the loop?

method, when invoked with argument DELAY, returns FALSE such that, when awaked,

activities re-execute the pre-control verification. Another difference, regarding method

preControl of Synchronization Interface Composition is, as seen above,

the use of method finish of Concurrent Synchronized Invocation Compo-

sition to make the result, ERROR, available when the invocation synchronization

returns an error.

To solve the problem of consistent composition of the destruction of the invocation

representation object, according to the policies of the two involved concerns, methods

delSyncInvocation and delConcInvocation in class Concurrent Synchro-

nized Invocation Composition have been redefined. Method delSyncInvo-

cation, presented in figure 9.13 only destroys the object if the object concurrency

policy no longer needs it, i.e., the object is destroyed if an invocation to delConcIn-

vocation has previously occurred. Method delConcInvocation follows a reverse

approach.

9.2.3 Application Layer

In the application layer, the concern and composition components are integrated

and customized according to the application’s functional objects being developed. In-

174 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

Execution_Status Concurrent_Synchronization_Associator::preControl(Concurrent_Synchronized_Invocation_CMP* invocation){

Execution_Status xStatus;

// pre-controldo{// begin mutual exclusionmutualExclusion_->lock();

// verify compatibilityxStatus = synchronizer_->preControl(invocation);

// Checks synchronization errorsif (xStatus == ERROR)

// finishes invocationinvocation->finish(ERROR);

// end mutual exclusionmutualExclusion_->unlock();

// if there are incompatibilities waitif (xStatus == DELAY)

concContext_->delay(invocation);}while (concContext_->loop(xStatus));

// return resultreturn xStatus;

}

Figure 9.12: Concurrency Synchronization Associator Class: preControl.

tegration and customization should be, respectively, transparent and incremental. The

characteristics of concern and composition components facilitate the implementation

of these properties.

Figure 9.14 presents the object-oriented framework’s application to a buffer.

The classes in figure 9.14 are:

� Client Object. Invokes the buffer’s operations using its abstract interface. It

corresponds to the pattern’s Client Object class.

� Real Buffer. This class implements the buffer. It corresponds to the patterns’

Functional Object class.

� Buffer Interface. Defines the buffer’s abstract interface.

� CONCERNS Interface Composition. Represents the Interface Compo-

sition classes of the object-oriented framework’s composition components.

9.2. OBJECT CONCURRENCY, SYNCHRONIZATION AND RECOVERY 175

void Concurrent_Synchronized_Invocation_CMP::delSyncInvocation(){

// the Synchronized invocation can be deleted

// if Concurrent invocation is in delete stateif (getConcStatus() == Concurrent_Invocation::DEL){delete this;

}else{// else the Synchronized invocation status is set to DELSynchronized_Invocation::delSyncInvocation();

}}

Figure 9.13: Concurrency Synchronized Invocation Composition Class:delSyncInvocation.

ClientObject

{abstract}

BufferInterface

{abstract}Composition

InterfaceCONCERNS

BufferCONCERNS

BufferReal

{private}

Figure 9.14: Class Buffer enriched with concerns.

� CONCERNS Buffer. Integrates the composition component with class Real

Buffer. It corresponds to the patterns’ Interface classes.

In order to guarantee transparent integration, two well known design patterns

have been applied: : Proxy and Abstract Factory (Gamma et al., 1994). The application

of the Proxy pattern is presented in figure 9.14. These patterns guarantee transparent

integration in the following way:

� According to the Proxy pattern, the definition of the buffer’s abstract interface pre-

vents the client object from knowing which Buffer Interface type is in use:

Real Buffer or CONCERNS Buffer. In addition, CONCERNS Buffer inherits

176 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

from class CONCERNS Interface Composition and uses the minimal inter-

face to carry out the integration. To avoid explicit creation, by client objects, of

instances of a specific CONCERNS Buffer class, the Abstract Factory pattern is

used. This pattern centralizes the creation of CONCERNS Buffer instances in a

factory which is used by client objects whenever they need to create a new ob-

ject of type Buffer Interface. The factory encapsulates the name of the class

from which objects are created. If a new concern is to be introduced, it is enough

to change the factory class.2

Finally, the following two code fragments show how the concern and composition

components presented in previous sections are, respectively, customized and integrat-

ed with the Real Buffer functional class.

class Synchronized_Buffer : public Buffer_Interface,private Synchronized_Interface_CMP

{public:

Synchronized_Buffer(int size): Buffer_Interface(size),

Synchronized_Interface_CMP(Synchronizer::PESSIMISTIC),buffer_(new Real_Buffer(size)),syncData_(new Buffer_Synchronization_Data(size))

{ }

...

private:Real_Buffer* buffer_;Buffer_Synchronization_Data* syncData_;

};

int Synchronized_Buffer::get(){

Synchronized_Invocation_CMP*invocation = createInvocation(new Get_Predicate<Synchronized_Invocation_CMP>(syncData_));

preControl(invocation);int value = buffer_->get();postControl(invocation);return value;

}

Figure 9.15: Synchronized Buffer Class: Definition (fragment) and get.

The definition of class Synchronized Buffer, a fragment of which is presented

in figure 9.15, integrates the COMPOSITION SYNCHRONIZED OBJECT component and

2It should be noted that integration using a design solution such as the Proxy pattern cannot solvethe problem of the functional object returning its identification, this in C++. This problem does notexist in an integration using a reflexive mechanism.

9.2. OBJECT CONCURRENCY, SYNCHRONIZATION AND RECOVERY 177

class Real Buffer. This class uses the pessimist object synchronization policy and

customizes, from the SYNCHRONIZED OBJECT concern component, class Synchro-

nization Data, to contain a buffer’s synchronization information (class Buffer

Synchronization Data in the code shown in the figure). Method get of class Syn-

chronized Buffer uses the COMPOSITION SYNCHRONIZED OBJECT componen-

t’s minimal interface (methods createInvocation, preControl, and postCon-

trol) to create an invocation object and synchronize the invocation on buffer . Class

Get Predicate is a customization for method get of the synchronization predicates

of the SYNCHRONIZED OBJECT concern component.

class Concurrent_Synchronized_Buffer: public Buffer_Interface,private Concurrent_Synchronized_Interface_CMP

{public:

Concurrent_Synchronized_Buffer(int size,Generator::Gen_Type genType,Concurrent_Synchronized_Associator::Assoc_Type assocType)

: Buffer_Interface(size),Concurrent_Synchronized_Interface_CMP(assocType, genType, Synchronizer::PESSIMISTIC),buffer_(new Real_Buffer(size)),syncData_(new Buffer_Synchronization_Data(size))

{ }

...

// synchronous interfaceint get();

// new get (concurrency model - asynchronous interface)void get(Future_T<int>* future);

private:Real_Buffer* buffer_;Buffer_Synchronization_Data* syncData_;

};

void Concurrent_Synchronized_Buffer::get(Future_T<int>* future){

createInvocation(new Get_Method_Object(buffer_, future),new Get_Predicate<Concurrent_Synchronized_Invocation_CMP>(syncData_));

}

int Concurrent_Synchronized_Buffer::get(){

Future_T<int> future;

// asynchronous invocationget(&future);

// synchronization with resultreturn future.getValue();

}

Figure 9.16: Concurrent Synchronized Buffer Class: Definition (fragment) andget.

178 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

The definition of class Concurrent Synchronized Buffer, a fragment of

which is presented in figure 9.16, integrates the COMPOSITION CONCURRENT SYN-

CHRONIZED OBJECT component with class Real Buffer. This class uses the pes-

simist object synchronization policy and allows both object concurrency and associa-

tion policies to be chosen at object creation time. It also customizes class Synchro-

nization Data, to contain a buffer’s synchronization information. The get meth-

ods of class Concurrent Synchronized Buffer are also presented in the figure,

one according to Buffer Interface, (int get()), the other providing an asyn-

chronous interface, (void get(Future T<int>*)). It should be noted that if the

client object wishes to use the concurrency capabilities of class Buffer’s new imple-

mentation, it has to explicitly use the new interface: void get(Future T<int>*).

This corresponds to a non-transparent situation caused by the use of another concur-

rency model. Method void get(Future T<int>*) uses the COMPOSITION CON-

CURRENT SYNCHRONIZED OBJECT component’s minimal interface (method cre-

ateInvocation) to create an invocation and to submit it for execution. Class Get

Predicate is the customization of the SYNCHRONIZED OBJECT concern componen-

t’s synchronization predicates for get. Class Get Method Object is the customiza-

tion of the CONCURRENT OBJECT concern component’s Method Object class for

get.

Incremental customization is guaranteed in the application layer as can be seen

by comparing figures 9.15 and 9.16. The Buffer Synchronization Data and Get

Predicate customizations of the SYNCHRONIZED OBJECT concern component are

used by both Synchronized Buffer and Concurrent Synchronized Buffer.

Object concurrency introduction needed only a new customization: Get Method Ob-

ject, of the CONCURRENT OBJECT concern component.

9.3 Related Work

Actalk (Briot, 1996) is the only approach for object synchronization and concur-

rency, known to us, based on object-oriented frameworks. This framework allows the

9.3. RELATED WORK 179

classification and customization of various synchronization policies. Actalk’s archi-

tecture consists of three classes called component classes. They are behavior, activi-

ty/synchronization, and communication classes. As mentioned in chapter 7, Actalk

does not separate synchronization from concurrency, joining both concerns in the

activity/synchronization component class. Moreover, Actalk has problems in com-

bining various versions of the same component class, since specialization of the ac-

tivity/synchronization component must provide synchronization and concurrency

customizations, as well as performing their composition. For instance, the activi-

ty/synchronization component includes a synchronization customization and a mu-

tual exclusion customization for executing synchronization code. Thus, combining

both synchronization customizations leads to a redefinition of the implementation of

mutual exclusion. It should be noted that in the three-layered framework this problem

does not appear, for the implementation of mutual exclusion is carried out in the com-

position layer, while the combination of two synchronization customizations is carried

out in the application layer, by composing objects Synchronization Predicate e

Synchronization Data.

The decomposition in components of finer granularity, proposed in the CodA re-

flective architecture (McAffer, 1995) seeks to avoid the problems of twice composing

the same component. The seven meta-objects which form the architecture must be cus-

tomized and composed among themselves in order to support the required concerns.

As mentioned in section 3.3.3, composition in this approach is complex, for it requires

an in-depth understanding of all responsibilities a meta-object has for different con-

cerns. Again, this problem arises from not having two composition levels as proposed

in the three-layered framework.

Kicsales et al.(1996) defines a set of rules for defining modules using reflection,

called open implementation (Maeda et al., 1997). These modules seek to establish a

trade-off between black-box reuse and white-box reuse (Kicsales, 1996). Thus, each

module offers a meta-interface through which the programmer is able to choose the

module’s implementation details, e.g. the implementation type of a list module. As

conclusion of his experiments with open implementation, Haines(1997) indicates, as

this approach’s main problem, the difficulties in composing meta-interfaces which are

180 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

not completely orthogonal. Once again, this problem arises from not defining two

composition levels, for composition and customization are carried out using the meta-

interface.

The only approach, we are aware of, that distinguishes an application layer from a

composition layer is described by Mulet et al.(1995) in the context of meta-object com-

position. In this approach, a composition architecture is defined which hides from the

final programmers the details of meta-object implementation and of their composition.

In addition, the approach identifies three properties meta-objects must possess in order

to be composed: encapsulation, independence (modularity), and exclusiveness. How-

ever, the approach does not consider the possibility of concern customization by the

user, for their customization is done jointly with their composition.

9.4 Results

The three-layered object-oriented framework with separation of concerns, de-

scribed in this chapter, has unique qualities, in the context of object-oriented frame-

works for concurrency, synchronization, and object recovery, in terms of flexibility and

expressiveness. In addition, the three-layered architecture allows solutions to some of

the traditional problems found in both construction and use of object-oriented frame-

works:

� Understandability. Object-oriented frameworks are designed after domain anal-

ysis. The domain is captured into the framework’s structure and collaborations.

However, users may not be domain specializes. This makes the use of the object-

oriented framework more difficult. The three-layered architecture provides layer-

s of both knowledge and description, thus facilitating understandability. More-

over, the programmer only needs to know the complexity associated with the

concerns to be applied.

� Inconsistent Specialization. Object-oriented frameworks allow a large degree of

flexibility in class specialization. Nevertheless, not all combinations of special-

9.4. RESULTS 181

ized classes are consistent. The three-layered object-oriented framework’s com-

position layer is responsible for guaranteeing consistent combination of different

policies. Those combinations are hidden from the final programmer, thus reduc-

ing the possibility of inconsistent specialization.

� Combinatorial Explosion. Frequently, specialization of one of the object-

oriented framework’s classes requires the specialization of other classes in a non-

controlled way. In the three-layered architecture, specializations are made with

component granularity, thus reducing combinatorial explosion.

The object-oriented framework allows both white-box and black-box reuse. Cus-

tomization of classes of concern components is white-box reuse, since the programmer

is required to know about the design pattern’s internal structure. Nevertheless, if the

programmer uses implementations of predefined policies, then this is black-box reuse,

since the programmer has only to create instances of customized classes and associate

them with the corresponding invocations. In addition, it should be noted that the com-

position components’ minimal interface also facilitates black-box reuse of composition

component classes.

The three-layered architecture also solves the orthogonality problems among con-

cerns. The concern and composition layers are responsible for making the composition

of concern customizations in the application layer completely orthogonal. This quality

is not to be found in any of the approaches we know of.

The framework’s architecture is independent from the integration mechanism used

in the application layer.

The three-layered object-oriented framework with separation of concerns was pub-

lished by Silva(1998). The object-oriented framework for object concurrency, syn-

chronization, and recovery, developed in C++ and using the abstract concurren-

cy and synchronization mechanisms provided by the ACE library is available at

http://www.esw.inesc.pt/˜ars/dasco/framework.html.

182 CHAPTER 9. OBJECT-ORIENTED FRAMEWORK

Part IV

Conclusion

183

10Results

This dissertation contains the following results and contributions:

� Definition of an approach with separation and composition of concerns integrat-

ing concurrent and object-oriented programming (Silva et al., 1995; Silva et al.,

1996d; Silva, 1997a; Silva et al., 1997b; Silva, 1997b; Silva, 1998; Silva et al.,

1999). This approach is based on object-oriented frameworks and has several

advantages when compared with other approaches based on separation of con-

cerns (Briot, 1989; Aksit et al., 1994a; McAffer, 1995; Briot, 1996; Kicsales et al.,

1997; Lopes & Kiczales, 1997; Lopes, 1997). In contrast with approaches by Ak-

sit et al.(1994a), Kicsales et al.(1997) and Lopes(1997), the proposed approach ex-

plicitly handles concern composition supporting composition policies. Regard-

ing the CodA (McAffer, 1995) and Actalk (Briot, 1996) approaches: in the pro-

posed approach it is easier to define each concern’s customization, for customiza-

tion is separated from composition and composition components encapsulate the

complexity of the combination of concern components.

The proposed approach has generic features which allow its use in contexts other

than that of concurrency. It has also been used in the context of distributed pro-

grams partitioning (Silva et al., 1995; Silva et al., 1996b; Goncalves & Silva, 1997;

Rosa & Silva, 1997; Silva et al., 1997a; Rosa & Silva, 1998; Silva et al., 1998).

� Documentation of the object-oriented framework for concurrency (Silva, 1998;

Silva et al., 1999). Solutions are described as design and composition patterns, us-

ing only basic concepts from the object-oriented paradigm. Descriptions are inde-

pendent from programming languages and integration mechanisms. In contrast

185

186 CHAPTER 10. RESULTS

with the CodA (McAffer, 1995) and Actalk (Briot, 1996) object-oriented frame-

works, which are implementations using Smalltalk, the proposed approach, in

addition to providing an implementation on C++, documents a general solution.

� Solution for the object concurrency concern. The solution is described by the Con-

current Object design pattern (a reduced version of this pattern was published by

Silva(1997b)). It has expressive power and allows separate reuse of object func-

tionality and object concurrency. In contrast with other approaches with separa-

tion of concerns (Aksit et al., 1994a; Lopes, 1997), the proposed approach handles

object concurrency as an independent concern and defines a solution which does

not mix object concurrency with object functionality. Other proposals for han-

dling object concurrency are at the mechanism abstraction level (Bershad et al.,

1988; Schmidt, 1995; Haines, 1997) or are less expressive (America, 1987; Yoneza-

wa et al., 1987; Caromel, 1990a; Karaorman & Bruno, 1993; Arjormandi et al.,

1995).

� Solution for the object synchronization concern. The solution is described by

the Synchronized Object design pattern (Silva et al., 1996d; Silva, 1997a). The so-

lution is more expressive than many language-based approaches (Campbell &

Habermann, 1974; Nierstrasz, 1987; Atkinson et al., 1991; Decouchant et al., 1991;

Neusius, 1991; Baquero et al., 1995). In contrast with the approaches by Kafu-

ra & Lee(1989), Tomlinson & Singh(1989), Bergmans(1994) and Lopes & Lieber-

herr(1994), it allows the definition of generic policies that completely sepa-

rate synchronization from functionality. In contrast with the approaches by

Grass & Campbell(1986), Caromel(1990a), Karaorman & Bruno(1993), Arjoman-

di et al.(1995), Briot(1996) and Lavender & Schmidt(1996), it separates object syn-

chronization from object concurrency. The ACE class library (Schmidt, 1995)

handles object synchronization only at the mechanism level. Approaches by M-

cHale(1994) and Briot(1996) are very expressive but, in contrast with the Synchro-

nized Object pattern, do not support optimist synchronization policies.

� Solution for the object recovery concern. The solution is described by the Recover-

able Object design pattern (Silva et al., 1997b). The solution allows the expression

187

of the two object recovery policies – update-in-place and deferred-update –, as

well as state recovery techniques: object copy and compensating operations. In

addition, the solution allows separate reuse of object functionality and object re-

covery. However, Recovery Objects may require a specific functional object

interface. There is no approach to the problem of object recovery based on class

libraries. Distributed systems considering object recovery (Liskov, 1988; Shrivas-

tava et al., 1991; Fazzolare et al., 1994), are less expressive than the Recoverable

Object pattern.

� Solution to the problem of non-orthogonal composition of concerns. The solution

is described by the Concurrent Synchronized Object, Synchronized Recoverable Object,

and Concurrent Synchronized Recoverable Object composition patterns. These com-

positions support the introduction of new policies, in contrast with approaches

in which composition is either automatic (Kicsales et al., 1997) or sequential (Ak-

sit et al., 1994a). Composition patterns preserve the properties of expressiveness,

modularity, encapsulation and reusability of the participating design patterns.

The composition of design patterns to describe object-oriented frameworks has

been described by Silva et al.(1999). Silva(1998) illustrates the problems of non-

orthogonal composition with the composition of the Synchronized Object and Ac-

tive Object patterns (Lavender & Schmidt, 1996). The latter corresponds to the

sequential object policy of the Concurrent Object pattern.

� Definition of an incremental development process of concurrent programs. This

process is described by a pattern language (Silva, 1997b). The pattern language

defines the activities that integrate design and composition patterns in a develop-

ment process where non-determinism associated with concurrent programming

may be introduced during the final stages. The language allows the assessment of

functional requirements without the need for developing the whole program and

allows solution customization according to each object’s specific needs. Com-

paring with other approaches (Rumbaugh et al., 1991; Jacobson, 1992; Shlaer &

J.Mellor, 1992; Booch, 1994; Coleman et al., 1994; Selic et al., 1994; Booch et al.,

1998) it does not create a gap between analysis and design models, hence not

needing automatic code generation to bridge that gap. In contrast with Karaor-

188 CHAPTER 10. RESULTS

man & Bruno(1993), through the distinction between explicit and implicit non-

functional requirements, it solves the conflict between reusability and incremen-

tal development. Moreover, the approach does not support just the transparency

model, as in the case of Caromel(1993).

� Definition of a three-layered architecture to support separation and composi-

tion of concerns (Silva, 1998). In contrast with McAffer(1995), Briot(1996) and

Kicsales et al.(1996), this architecture separates concern composition from con-

cern customization. As in the proposal by Mulet et al.(1995), the composition’s

complexity is hidden from the final programmers, thus simplifying use of the

architecture. In spite of the composition’s encapsulation, and in contrast with

Mulet et al.(1995), we allow programmers to adapt concerns independently from

composition. Also in contrast with all of the previous approaches, our architec-

ture is independent from integration mechanisms.

� Implementation, in C++, of design and composition patterns according to a three-

layered object-oriented framework with separation of concerns (Silva, 1998).

The approach has been used in the development and support of a cooperative work

system (Alves & Silva, 1997; Antunes, 1997). This use allows us to conclude about this

approach’s usefulness in the development of such systems (Alves & Silva, 1997).

Component-based programming and its composition environments constitute a

particularly active research area. Both the object-oriented framework and the architec-

ture proposed in this dissertation fulfill the requirements of a component composition

environment as presented by Meijler & Nierstrasz(1998):

� Final programmers develop programs through composition of functional and

generic components, i.e., black-box reuse.

� Component programmers build black-box components by identifying useful ab-

stractions. Black-box component implementation may include white-box reuse.

Finally, an initial version of the proposed approach has been integrated by

Berre et al.(1997) in a role-based methodology (Reenskaug et al., 1996) according to

189

the RM-ODP model (Reference Model - Open Distributed Processing) (RM-ODP, 1995). In

the context of RM-ODP, work from the organizational viewpoint has been carried out

on the role of non-functional distribution and concurrency models in organizational

modeling (Silva et al., 1996e; Silva et al., 1997c). This work is beyond the scope of this

dissertation and, hence, its description has not been included.

190 CHAPTER 10. RESULTS

11Future Work

Two areas exist we envision as object of future work following the results achieved

in this dissertation: coordination and role-based design.

11.1 Coordination

The properties associated with the behavior of groups of entities have been stud-

ied by different disciplines such as, for instance, transactions (Gray & Reuter, 1993)

and database federation (Sheth & Larson, 1990). Coordination (Malone & Crowston,

1994) is a new discipline integrating these different perspectives about the behavior of

groups of entities. A definition of coordination is given by Cruz et al.(1996) as being the

discipline which deals with behavior organization, in time and space, of groups of en-

tities in order to improve their results and reduce their conflicts. Problems handled by

coordination include: resource sharing, producer/consumer, concurrency restriction-

s, and dependencies between tasks and sub-tasks (Malone & Crowston, 1994). It has

been verified that synchronization and concurrency are special cases of coordination.

Thus, a line for future work is the extension of the results obtained in this dissertation

to the more general context of coordination.

Some approaches for handling coordination are centered on:

� Multi-object coordination, in which restrictions on object behavior are defined

to ensure properties, such as synchronization, associated with a group of object-

s (Frolund & Agha, 1993; Mukherji & Kafura, 1995; Frolund, 1996; Papathomas,

191

192 CHAPTER 11. FUTURE WORK

1996). Solutions to these problems must possess object-oriented programming

properties, such as coordination reusability and functionality encapsulation.

Several languages proposed for coordinating invocations on a group of object-

s exist (Frolund & Agha, 1993; Mukherji & Kafura, 1995; Frolund, 1996). An

example of this type of coordination is the behavior restriction of two resource

managers which together cannot make available more than a given total number

of resources.

Papathomas(1996) proposes a construct to support coordination when objects

possess internal activities which are not associated with, nor are caused by, invo-

cations. In this situation, the previous proposals cannot be applied as the objects

must synchronize their execution with events occurring within other objects. An

example of this type of coordination is the explicit coordination of two internal

activities, associated with two objects generating video image and sound track.

� Activity coordination, in which restrictions on activity behavior are defined to

ensure properties, such as execution order, associated with activities accessing

objects (Weihl, 1989; Guerraoui, 1994). As in multi-object coordination, solutions

must possess object-oriented programming properties.

One of the most common inter-activity dependency is activity atomicity when

accessing a group of objects. For instance, Weihl(1989) shows how global atom-

icity can be obtained using just the local atomicity of each object accessed by an

activity. According to Weihl, it is necessary that all objects use the same local

atomicity policy in order to obtain global atomicity. Guerraoui(1994) proposes

an object system supporting global atomicity in which objects may use different

local atomicity policies.

Results from the synchronized object concern can be extended to account for the

case of multi-object coordination using as a basis the coordination of its invocations.

For instance, it is relatively simple to apply the Synchronized Object pattern to a group of

objects. This is done in the following way: (i) a single instance of Synchronization

Data to be shared by all objects is created; (ii) each object possesses a synchronization

11.1. COORDINATION 193

interface which uses using objects Synchronizer and Synchronization Pred-

icate. In this way, the two managers problem is solved if the Synchronization

Data shared object contains information on the total number of affected resources. N-

evertheless, it is not possible to apply the Synchronized Object pattern if the coordination

is not associated with invocation occurrence.

We have already concluded some of the work dealing with activity coordination.

The work has been based on activity-specific information representation. This infor-

mation is crucial as, for instance, in the system proposed by Guerraoui, it is necessary

to preserve information on each activity to implement the global atomicity policy. We

have defined a system supporting different global and local atomicity policies (Pereira,

1994; Silva et al., 1996a). This system was later rewritten by Silva et al.(1996c) using de-

sign patterns in which activities are represented as objects. In this way we achieved

our goal of supporting an activity’s specific information to decide about its synchro-

nization. Moreover, it is possible to extend the Synchronized Object pattern in order to

enable Synchronization Predicate objects to detect the activity responsible for

an invocation and to obtain synchronization information associated with that activity.

Once that information is available, predicates may proceed to the local synchroniza-

tion according to the global atomicity policy. The Synchronized Object pattern must be

extended to support other inter-activity dependencies beyond global atomicity.

Future work in the coordination area consists of:

� Definition of both design and composition patterns, new ones or obtained by

extending the ones proposed in this dissertation, to support: synchronization

information shared by different objects; the concept of activity and its synchro-

nization; and activity recovery.

� Identification of coordination needs in CSCW (Computer-Supported Cooperative

Work) programs (Rodden & Blair, 1991), especially in multi-user object-oriented

environments (Haynes & Holmevik, 1998); and, definition and application of de-

sign patterns for coordination in that context.

194 CHAPTER 11. FUTURE WORK

11.2 Role-based Design

Design patterns (Gamma et al., 1994) allow descriptions at a higher abstraction lev-

el than that of code. For that, design patterns focus their attention on responsibilities

and collaborations of a set of design entities. Still, representing these design entities as

classes and objects makes comprehension difficult, especially when several design pat-

terns are composed: class interfaces do not distinguish between different ways of using

the classes, thus not allowing their use to be shown in different specific contexts; col-

laborations in which an object participates may be complex and serve different needs.

To deal with the lack of clarity inherent to the use of objects and classes to represen-

t design, class diagrams have been used, in chapter 7, which emphasize the origin of

responsibilities associated with each class (Eriksson & Penker, 1998). However, design

patterns associate responsibilities with classes at early stages, sometimes making it nec-

essary for composition patterns to alter those associations. For instance, in figure 4.3,

concerning the Concurrent Object pattern, class Concurrency Interface is respon-

sible for the interaction with class Generator, while in figures 7.4 and 7.5, concerning

the Concurrent Synchronized Object pattern, that is the responsibility of class Associa-

tor. It can be concluded that the class concept has been used more as a responsibility

container than as an interface definition. This option is close to recent proposals for

role-based design (Riehle, 1996; Riehle, 1997; Riehle & Gross, 1998).

Riehle’s current work, following Reenskaug’s work (Reenskaug et al., 1992; Reen-

skaug et al., 1996), on design patterns, pattern composition and object-oriented

frameworks representation using role models is a particularly interesting proposal.

Riehle & Gross(1998) describe a meta-model for role models containing the following

concepts:

� Role and Role Type. A role type describes a view that an object has of another

object. An object performs the roles specified by its set of role types.

� Object and Class. An object represents a phenomenon within a domain. A class

is an abstraction of a set of identical objects: its instances. A class has a set of role

types and specifies how they are combined in its instances.

11.2. ROLE-BASED DESIGN 195

� Role Model. A role model describes a set of collaborations between role types.

Role types are related by association and aggregation relationships. Role mod-

els are composed using role constraints. Role constraints indicate possible role

combinations.

� Class Model. A class model describes a set of classes related by inheritance and

by association and aggregation relationships defined by their role types. The

inheritance relationship must respect the set of role types of the involved classes:

a subclass must possess all of its superclass’ role types.

By using these concepts, Riehle shows that (i) design patterns may be described

using role models; (ii) pattern compositions may be described as compositions of the

role models of the participating design patterns; and (iii) object-oriented frameworks

may be described using class models including role models of both design patterns

and pattern compositions.

Riehle concludes that, by using role-based design descriptions, the aforementioned

complexity problems are solved: a role type defines the way a class instance interacts

in a given context; and each role model defines a specific collaboration.

We think the results of this dissertation may be explored and extended in the con-

text of role-based design. The work we envision consists of the definition of design

and composition patterns and of the three-layered object-oriented framework, using

roles to:

� Integrate the policy compatibility constraints of composition patterns with role

constraints associated with role model composition.

� Define the kinds of relation between the object-oriented framework’s three layers,

in terms of the kinds of relation between the class models associated with each

component of the object-oriented framework.

196 CHAPTER 11. FUTURE WORK

12Epilogue

12.1 Summary

The development of concurrent object-oriented programs, from a software engi-

neering perspective, must possess a set of features to allow control of its inherent com-

plexities, such as non-determinism and multiplicity of existing technological supports.

If, on the one hand, the problem posed by this multiplicity is solved by defining an

approach at the policies abstraction level, which hides mechanism specificities when

implementing policies, on the other hand, non-determinism demands more elaborate

techniques rooted on a divide-and-conquer strategy.

To solve these problems, this dissertation defines an approach for constructing con-

current object-oriented programs that separates a program’s functionality from its con-

currency and identifies various concurrency concerns that must be dealt with in isola-

tion. The approach consists of the following elements:

� Design Patterns for each concurrency concern - Concurrent Object, Synchronized Ob-

ject, Recoverable Object - which possess the following properties: expressiveness,

for they support several policies; modularity, for they separate functionality code

from concern code; encapsulation, for they hide from client objects the concern’s

code; and reusability, for functionality code and concern code can be reused and

extended separately.

� Composition patterns - Concurrent Synchronized Object, Synchronized Recoverable Ob-

ject, Concurrent Synchronized Recoverable Object - which consistently combine de-

sign patterns preserving their properties.

197

198 CHAPTER 12. EPILOGUE

� A Pattern language which integrates design and composition patterns in an in-

cremental development process for concurrent programs, where functionality re-

quirements are fulfilled first, and concurrency is later introduced by horizontal

increments of concurrency concerns. Introduction of non-determinism is delayed

in order to facilitate testing and debugging of programs.

� An Object-oriented framework which implements design and composition patterns

according to a three-layered architecture with separation of concerns. This ar-

chitecture allows the programmer to customize in a simple way each pattern’s

policies to the specific needs of the program being constructed. Furthermore, the

object-oriented framework allows pre-defined customizations to be used by the

programmer, without the need to be aware of the inherent complexity of both

the problem dealt with by the concern and the solution described by the design

pattern.

These elements, as well as their properties, give the approach the features required

by a software engineering discipline:

� Separation of concerns - by separately handling functional and non-functional re-

quirements of concurrent programs and by separating concurrency concerns.

� Generality - through the expressiveness of both design and composition patterns,

which support various policies.

� Anticipation of change - through modularity and encapsulation of both design and

composition patterns, which allow a concern’s policies to be changed without

changing the functional object, its client objects, or other concerns’ policies.

� Abstraction - through the object-oriented framework’s flexibility, which allows use

of both predefined policies and customization of policies according to specific

needs.

� Object-oriented framework Documentation through both design and composition

patterns.

12.2. ACHIEVEMENT OF GOALS 199

� Incrementality - through both the pattern language and the properties of design

and composition patterns, as they allow separate introduction of concurrency

concerns and substitution of their policies.

� Modularity - through both the modularity of design and composition patterns

and its implementation in the object-oriented framework. The framework defines

components with high cohesion and low coupling and hides the complexities of

component composition.

The approach’s suitability was tested by developing a cooperative work system.

The results of this experiment indicate that the approach’s flexibility and incremental-

ity features make it especially convenient for this kind of system.

12.2 Achievement of Goals

The specific goals proposed in this dissertation are:

� The integration of concurrent and object-oriented programming must have ex-

pressiveness and simplicity, and allow reuse and incremental development.

� The integration must solve conflicts between reuse and inheritance, where func-

tionality and concurrency must be separately reusable and extendible; and reuse

and incremental development, where the introduction of concurrency must not lead

to changes to the interfaces of objects previously defined for the program’s se-

quential version.

The properties of this approach allow satisfaction of the following requirements:

� The expressiveness requirement is fulfilled through the expressiveness proper-

ty of both design and composition patterns. Design patterns support concern-

s’ policies, and composition patterns combine the policies of design patterns

and support new policies appearing due to the composition. Simplicity of use

200 CHAPTER 12. EPILOGUE

and customization follow from the object-oriented framework’s incremental cus-

tomization property. The framework allows expressiveness with simplicity, as

non-orthogonal composition issues are encapsulated and thus hidden from the

final programmer.

� The reusability requirement is fulfilled through the modularity, encapsulation,

and reusability properties of both design and composition patterns.

� The incremental development requirement is supported by the pattern language

and is also based on the modularity, encapsulation, and reusability properties of

both design and composition patterns.

The conflicts between reuse and inheritance and between reuse and incremental

development are also solved by the proposed approach.

The modularity property of both design and composition patterns avoids the con-

flict between reuse and inheritance as it defines an inheritance hierarchy for each con-

cern separate from the functionality inheritance hierarchy. Thus, functionality and con-

currency can be separately reused.

The pattern language solves the conflict between reuse of the sequential version

and the incremental introduction of concurrency. This is done through identifica-

tion of both implicit and explicit non-functional requirements and through use of

“non-concurrent” policies of design patterns. The former allows identification of non-

functional requirements having repercussions on the interface of objects and, conse-

quently, must be considered when constructing the sequential version. The later allows

sequential implementation of explicit non-functional requirements in the program’s se-

quential version.

Finally, it has been verified as possible to orthogonally compose different concerns.

This was not obvious before this work was done. The responsibilities hierarchy de-

fined by the three-layered architecture allows the complexity of non-orthogonal com-

position to be isolated from the final programmer, thus allowing orthogonal and incre-

mental customization of concerns. Therefore, it is claimed that this architecture, jointly

with the properties of its components, constitutes a reference model for the problem of

12.3. FINAL REMARKS 201

concern composition. As a way of verification, the architecture was also successfully

tested in the composition of distribution concerns.

12.3 Final Remarks

As a consequence of both this work and this dissertation’s results, a few aspects

have emerged deserving final reflection.

Separation of explicit and implicit non-functional requirements. We conclud-

ed that the distinction between explicit and implicit non-functional requirements and

their identification during the initial phases of development is crucial for incremental

development. We have also found that user models are given by the non-functional

requirements of the program’s interface. An in-depth study of the user models and

their transformation in non-functional requirements of architecture components re-

mains open. This research is part of the more general area of the transformation of

requirements into analysis and design models.

We believe that the distinction between explicit and implicit non-functional re-

quirements is crucial for the definition and evaluation of a component’s quality of

service, as well as for its integration in the definition of architectures of components.

Separation between abstraction definition and integration mechanisms. In this

dissertation a clear boundary has been defined between the definition of abstractions

(e.g. object synchronization) and integration mechanisms (e.g. reflection). We found

that this separation simplifies the definition of abstractions, since abstractions become

independent of integration mechanisms, thus, orthogonal to the latter’s problems. For

instance, the fact that a functional object can return its identification should not have

implications at the abstraction design level. This is not the case of other solutions.

Moreover, the proposed separation allows an in-depth study of the properties of in-

tegration mechanisms as well as of the requirements each of them imposes on the

properties of abstractions. As an example of the latter, note that reflection requires

abstractions to provide quiescent states.

202 CHAPTER 12. EPILOGUE

We believe that (i) the use of role models to describe abstractions makes this sep-

aration even more clear; and (ii) that integration mechanisms should appear by trans-

forming role models into class models, where the features of integration mechanisms

are made explicit.

Separation of the definition of abstractions and their implementations. We found

that the separation between the definition of abstractions and their implementations

allows this definition to center itself on its structural properties, such as modularity,

without being biased by non-structural requirements, such as performance. We found

that the complexity inherent to supporting the stated structural properties, apparent

in the large number of classes, does not necessarily have consequences in the imple-

mentation. The reverse is true: these design abstractions lead to the identification and

implementation of only those classes strictly needed to support the desired properties

for each case, and they create the possibility of leaving out all the ones related to the

undesirable structural properties.

Also in this case, we believe that the use of role models to describe abstractions

enables us to define which roles can be attributed to the same class, as well as the

conditions for that attribution. In this way, the possible implementations of design

abstractions may be explicitly studied.

Bridging the gap between sequential and concurrent programs. Identifying dif-

ferent concerns of concurrent programs and recognizing that after all some of them,

such as synchronization based on an object’s state, are also concerns of sequential pro-

grams, enabled us to build a bridge between these two kinds of programs. We found,

thus, that a program is not characterized as concurrent or sequential, but rather by the

set of concerns it considers.

We believe that the disappearance of this gap, in addition to allowing incremental

development, also reduces the conceptual gap perceived by programmers when they

build their programs. Thus, programmers need not distinguish between sequential

and concurrent programs: they have only to consider the set of concerns associated

with each program.

ABibliography

AARSTEN, AMUND. 1997. Object-Oriented Design Patterns in Distributed Systems. Ph.D.

thesis, DAI, Politecnico di Torino, Italy.

AARSTEN, AMUND, ELIA, GABRIELE, & MENGA, GIUSEPPE. 1995. G++: A Pattern

Language for the Object Oriented Design of Concurrent and Distributed Informa-

tion Systems, with Applications to Computer Integrated Manufacturing. Pages

91–118 of: COPLIEN, JIM, & SCHMIDT, DOUGLAS C. (eds), Pattern Languages of

Program Design. Addison-Wesley.

AGHA, GUL. 1986. ACTORS: A Model of Concurrent Computation in Distributed Systems.

MIT Press.

AKSIT, MEHMET. 1996. Composition and Separation of Concerns in the Object-

Oriented Model. ACM Computing Surveys, 28A(4).

AKSIT, MEHMET. 1997 (June). Issues in Aspect-Oriented Software Development. Presented

at the ECCOP’97 Workshop on Aspect-Oriented Programming.

AKSIT, MEHMET, WAKITA, KEN, BOSCH, JAN, BERGMANS, LODEWIJK, & YONEZAWA,

AKINORI. 1994a. Abstracting Object Interactions Using Composition Filters. Pages

152–184 of: GUERRAOUI, RACHID, NIERSTRASZ, OSCAR, & RIVEILL, MICHELL

(eds), Proceedings of the ECOOP’93 Workshop on Object-Based Distributed Program-

ming. Lecture Notes in Computer Science, vol. 791. Springer-Verlag.

AKSIT, MEHMET, BOSCH, JAN, VAN DER STERREN, WILLIAM, & BERGMANS, LODEWI-

JK. 1994b (July). Real-Time Specification Inheritance Anomalies and Real-Time

Filters. Pages 386–405 of: ECOOP ’94.

203

204 BIBLIOGRAPHY

ALEXANDER, CHRISTOPHER. 1977. A Pattern Language: Towns, Buildings, Construction.

Oxford University Press.

ALEXANDER, CHRISTOPHER. 1979. The Timeless Way of Building. Oxford University

Press.

ALVES, CARLOS, & SILVA, DANIEL. 1997 (Setembro). Suporte e Controlo da Interaccao

em Sistemas de Trabalho Cooperativo. Relatorio do Trabalho Final de Licenciatura em

Engenharia Informatica e de Computadores.

AMERICA, PIERRE. 1987. POOL-T: A Parallel Object-Oriented Language. Pages 199–220

of: YONEZAWA, AKINORI, & TOKORO, MARIO (eds), Object-Oriented Concurrent

Programming. MIT Press.

AMERICAN NATIONAL STANDARDS INSTITUTE, INC. (ed). 1983. The Programming Lan-

guage ADA Ference Manual. LNCS 155, Springer-Verlag.

ANDREWS, GREGORY R., & SCHNEIDER, FRED B. 1983. Concepts and Notation for

Concurrent Programming. ACM Computing Surveys, 15(1), 3–43.

ANDREWS, GREGORY R., OLSSON, R.A., & COFFIN, M. 1988. An Overview of the SR

Language and Implementation. TOPLAS, 10(1), 51–86.

ANTUNES, PEDRO. 1997 (May). A System for Supporting and Managing Same-

Time/Different-Place Group Interactions. Pages 216–225 of: ACM Working Con-

ference on Advanced Visual Interfaces (AVI ’98).

ARJORMANDI, ESHRAT, O’FARREL, WILLIAM G., KALAS, IVAN, KOBLENTS, GITA, EI-

GLER, FRANK CH., & GAO, GUANG G. 1995. ABC++: Concurrency by Inheritance

in C++. IBM Systems Journal, 34(1), 120–136.

ARNOLD, KEN, & GOSLING, JAMES. 1996. The Java Programming Language. Addison-

Wesley.

ATKINSON, COLIN, GOLDSACK, STEPHEN, DI MAIO, ANDREA, & BAYAN, R. 1991.

Object-Oriented Concurrency and Distribution in DRAGOON. Journal of Object-

Oriented Programming, 4(1), 11–18.

BIBLIOGRAPHY 205

BAQUERO, CARLOS, OLIVEIRA, RUI, & MOURA, FRANCISCO. 1995. Integration of

Concurrency Control in a Language with Subtyping and Subclassing. In: Confer-

ence on Object Oriented Technologies and Systems. Usenix Association.

BECK, KENT, & CUNNINGHAM, WARD. 1987 (October). Using Pattern Languages for

Object-Oriented Programs. OOPSLA ’87 Workshop on the Specification and Design

for Object-Oriented Programming.

BERGMANS, LODEWIJK. 1994. Composing Concurrent Objects: Applying Composition Fil-

ters to the Development and Reuse of Concurrent Object-Oriented Programs. Ph.D. the-

sis, Department of Computer Science of the University of Twente in The Nether-

lands.

BERNSTEIN, PHILIP A., & GOODMAN, NATHAN. 1987. Concurrency Control and Recov-

ery in Database Systems. Addison-Wesley.

BERRE, ARNE-JORGEN, AAGEDAL, JAN OYVIND, & SILVA, ANTONIO RITO. 1997 (Jan-

uary 7-10). SIMOD - An ODP-extended Role-Modeling Methodology for Dis-

tributed Objects. Pages 14–23 of: IEEE 30-th Hawaii International Conference on Sys-

tem Sciences (HICSS-30), Object-Oriented Methods for Distributed Applications Track.

BERSHAD, BRIAN, LAZOWSKA, EDWARD, & LEVY, HENRY. 1988. PRESTO: A System

for Object-oriented Parallel Programming. Software: Practice and Experience, 18(8),

713–732.

BLOOM, TOBY. 1979 (December). Evaluating Synchronization Mechanisms. Pages 24–

32 of: Proceedings of the Seventh Symposium on Operating System Principles.

BOOCH, GRADY. 1994. Object-Oriented Analyis and Design with Applications. The Ben-

jamin/Cummings Publishing Company, Inc.

BOOCH, GRADY, RUMBAUGH, JAMES, & JACOBSON, IVAR. 1998. The Unified Modeling

Language User Manual. Addison-Wesley.

BRIOT, JEAN-PIERRE. 1989 (July). Acttalk: A Testbed for Classifying and Designing

Actor Languages in the Smalltalk-80 Environment. Pages 109–129 of: ECOOP ’89.

206 BIBLIOGRAPHY

BRIOT, JEAN-PIERRE. 1996 (March). An Experiment in Classification and Specializa-

tion of Synchronization Schemes. Pages 227–249 of: 2nd International Symposium on

Object Technologies for Advanced Software.

BRIOT, JEAN-PIERRE, GUERRAOUI, RACHID, & LOHR, KLAUS-PETER. 1998. Concur-

rency and Distribution in Object-Oriented Programming. ACM Computing Surveys,

30(3), 291–329.

BUSCHMANN, FRANK, MEUNIER, REGINE, ROHNERT, HANS, SOMMERLAD, PETER, &

STAL, MICHAEL. 1996. Pattern-Oriented Software Architecture: A System of Patterns.

John Wiley and Sons.

CAMPBELL, ROY, & HABERMANN, A. 1974. The Specification of Process Synchro-

nization by Path Expressions. In: GELENBE, E., & KAISER, C. (eds), International

Symposium on Operating Systems, LNCS 16. Springer/Verlag.

CAROMEL, DENIS. 1990a. Concurrency And Reusability: From Sequential To Parallel.

Journal of Object-Oriented Programming, 3(3), 34–42.

CAROMEL, DENIS. 1990b (November). Programming Abstractions for Concurrent Pro-

gramming. Pages 245–253 of: Technology of Object-Oriented Languages and Systems

(TOOLS Pacific’90).

CAROMEL, DENIS. 1993. Towards a Method of Object-Oriented Concurrent Program-

ming. Communications of the ACM, 36(9), 90–102.

COLEMAN, DEREK, HAYES, FIONA, & BEAR, STEPHEN. 1992. Introducing Objectcharts

or How to Use Statecharts in Object-Oriented Design. IEEE Transactions on Software

Engineering, 18(1), 9–18.

COLEMAN, DEREK, ARNOLD, PATRICK, BODOFF, STEPHANIE, DOLLIN, CHRIS,

GILCHRIST, HELENA, HAYES, FIONA, & JEREMES, PAUL. 1994. Object-Oriented

Development: The Fusion Method. Prentice-Hall.

COPLIEN, JAMES. 1995. A Generative Development-Process Pattern Language. Pages

183–238 of: COPLIEN, JAMES, & SCHMIDT, DOUGLAS (eds), Pattern Languages of

Program Design. Addison-Wesley.

BIBLIOGRAPHY 207

COPLIEN, JAMES, & SCHMIDT, DOUGLAS (eds). 1995. Pattern Languages of Program

Design. Addison-Wesley.

CRUZ, JOAO. 1997 (Outubro). Instrumentacao Incremental de Aplicacoes Concorrentes. Tese

de Mestrado/Master Thesis, Instituto Superior Tecnico, Universidade Tecnica de

Lisboa, Lisboa, Portugal.

CRUZ, JUAN CARLOS, TICHELAAR, SANDER, & NIERSTRASZ, OSCAR. 1996. A

Coordination Component Framework for Open Systems. Tech. rept. SCG Re-

port,IAM,University of Bern.

DECOUCHANT, D., DOT, P. LE, RIVEILL, M., ROISIN, C., & DE PINA, X. ROUSSET.

1991 (May). A Synchronization Mechanism for an Object-Oriented Distributed

System. Pages 152–159 of: Proceedings of the 11th International Conference on Dis-

tributed Computing Systems.

DIJKSTRA, E. W. 1968. Cooperating Sequential Processes. Pages 43–112 of: GENUYS, F.

(ed), Programming Languages. Academic Press.

ERIKSSON, HANS-ERIK, & PENKER, MAGNUS. 1998. UML Toolkit. Wiley.

FAZZOLARE, MICHAEL, HUMM, BERNHARD G., & RANSON, R. DAVID. 1994. Object-

Oriented Extendibility in Hermes/ST, a Transactional Distributed Programming

Environment. Pages 240–261 of: GUERRAOUI, RACHID, NIERSTRASZ, OSCAR, &

RIVEILL, MICHELL (eds), Proceedings of the ECOOP’93 Workshop on Object-Based

Distributed Programming. Lecture Notes in Computer Science, vol. 791. Springer-

Verlag.

FORMAN, IRA, DANFORTH, SCOTT, & MADDURI, HARI. 1994 (October). Composition

of Before/After Metaclasses in SOM. Pages 427–439 of: OOPSLA’94.

FROLUND, SVEND. 1992 (June/July). Inheritance of Synchronization Constraints

in Concurrent Object-Oriented Programming Languages. Pages 185–196 of: E-

COOP’92.

FROLUND, SVEND. 1996. Coordinating Distributed Objects. MIT Press.

208 BIBLIOGRAPHY

FROLUND, SVEND, & AGHA, GUL. 1993 (July). A Language Framework for Multi-

Object Coordination. Pages 346–360 of: ECOOP ’93.

GAMMA, ERICH, HELM, RICHARD, JOHNSON, RALPH, & VLISSIDES, JOHN. 1993 (Ju-

ly). Design Patterns: Abstraction and Reuse of Object-Oriented Design. Pages

406–431 of: ECOOP ’93.

GAMMA, ERICH, HELM, RICHARD, JOHNSON, RALPH, & VLISSIDES, JOHN. 1994. De-

sign Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley.

GHEZZI, CARLO, JAZAYERI, MEHDI, & MANDRIOLI, DINO. 1991. Fundamentals of Soft-

ware Engineering. Prentice-Hall.

GOLDBERG, ADELE, & ROBSON, DAVID. 1983. Smalltalk-80 The Language and Its Imple-

mentation. Reading, Massachusetts: Addison-Wesley.

GONCALVES, TERESA, & SILVA, ANTONIO RITO. 1997 (July). Passive Replicator: A

Design Pattern for Object Replication. Pages 165–178 of: The 2nd European Conference

on Pattern Languages of Programming, EuroPLoP ’97.

GRASS, J. E., & CAMPBELL, R. H. 1986. Mediators: A Synchronization Mechanis-

m. Pages 486–477 of: 6th International Conference on Distributed Computing Systems.

IEEE.

GRAY, JIM, & REUTER, ANDREAS. 1993. Transaction Processing: Concepts and Techniques.

Morgan Kaufmann Publishers.

GUERRAOUI, RACHID. 1994 (July). Atomic Object Composition. Pages 118–138 of: E-

COOP’94.

HAINES, MATTHEW. 1997 (October). An Open Implementation Analysis and Design

for Lightweight Threads. Pages 229–242 of: Conference on Object-Oriented Program-

ming Systems, Languages and Applications, Proceedings.

HAYNES, CYNTHIA, & HOLMEVIK, JAN RUNE (eds). 1998. High Wired: On the Design,

Use, and Theory of Educational MOOs. University of Michigan Press.

BIBLIOGRAPHY 209

HOARE, C. A. R. 1974. Monitors: An Operating System Structuring Concept. Comuni-

cations of the ACM, 17(10), 549–557.

HOARE, C. A. R. 1985. Communicating Sequential Processes. Prentice-Hall.

HURSCH, WALTER, & LOPES, CRISTINA VIDEIRA. 1995 (February). Separation of Con-

cerns. Tech. rept. NU-CCS-95-03. College of Computer Science, Northeastern Uni-

versity.

HUTT, ANDREW T.F. (ed). 1994a. Object Analysis and Design: Comparation of Methods.

OMG, John Wiley.

HUTT, ANDREW T.F. (ed). 1994b. Object Analysis and Design: Description of Methods.

OMG, John Wiley.

JACKSON, MICHAEL. 1995. Software Requirements and Specifications. Addison-Wesley.

JACOBSON, IVAR. 1992. Object-Oriented Software Engineering. Addison-Wesley.

JOHNSON, RALPH E. 1992 (October). Documenting Frameworks using Patterns. Pages

63–76 of: OOPSLA ’92, Proceedings.

JOHNSON, RALPH E., & FOOTE, BRIAN. 1988. Designing Reusable Classes. Journal of

Object-Oriented Programming, 1(2), 22–35.

KAFURA, DENNIS, & LEE, KEUNG HAE. 1989 (July). Inheritance in Actor Based Con-

current Object-Oriented Languages. Pages 131–145 of: ECOOP ’89.

KARAORMAN, MURAT, & BRUNO, JOHN. 1993. Introducing Concurrency to a Sequen-

tial Language. Communications of the ACM, 36(9), 103–116.

KICSALES, GREGOR. 1996. Beyond the Black Box: Open Implementation. IEEE Soft-

ware, 13(1), 8–11.

KICSALES, GREGOR, DES RIVIERES, JIM, & BOBROW, DANIEL. 1991. The Art of the

Meta-Object Protocol. MIT Press.

210 BIBLIOGRAPHY

KICSALES, GREGOR, LAMPING, JOHN, LOPES, CRISTINA VIDEIRA, MAEDA, CHRIS,

MENDHEKAR, ANURAG, & MURPHY, GAIL. 1996 (May). Open Implementation

Design Guidelines. In: 19th International Conference on Software Engineering.

KICSALES, GREGOR, LAMPING, JOHN, MENDHEKAR, ANURAG, MAEDA, CHRIS,

LOPES, CRISTINA, LOINGTIER, JEAN-MARC, & IRWIN, JOHN. 1997 (February).

Aspect-Oriented Programming. Tech. rept. SPL97-008 P9710042. XEROX PARC.

KRAMER, J., & MAGEE, J. 1985. Dynamic Configuration for Distributed Systems. IEEE

Transactions on Software Engineering, SE-11(4), 424–436.

KRASNER, GLENN E., & POPE, STEPHEN T. 1988. A Cookbook for Using the

Model-View-Controller User Interface Paradigm in Smalltalk-80. Journal of Object-

Oriented Programming, 1(3), 26–49.

LAVENDER, R. GREG, & SCHMIDT, DOUGLAS C. 1996. Active Object: an Object Behav-

ioral Pattern for Concurrent Programming. Pages 483–499 of: VLISSIDES, JOHN M.,

COPLIEN, JAMES O., & KERTH, NORMAN L. (eds), Pattern Languages of Program

Design 2. Addison-Wesley.

LISKOV, BARBARA. 1988. Distributed Programming in Argus. Communications of the

ACM, 31(3), 300–312.

LISKOV, BARBARA, HERLIHY, MAURICE, & GILBERT, LUCY. 1986 (January). Limita-

tions of Synchronous Communication with Static Process Structure in Languages

for Distributed Computing. Pages 150–159 of: Proceedings of the ACM 13th Sympo-

sium on Principles of Programming Languages.

LOHR, KLAUS-PETER. 1992 (October). Concurrency Annotations. Pages 327–340 of:

OOPSLA ’92, Proceedings.

LOPES, CRISTINA VIDEIRA. 1997 (September). D: A Language Framework for Distributed

Programming. Ph.D. thesis, College of Computer Science of Northeasthern Univer-

sity, Boston.

BIBLIOGRAPHY 211

LOPES, CRISTINA VIDEIRA, & KICZALES, GREGOR. 1997 (February). D: A Language

Framework for Distributed Programming. Tech. rept. SPL97-010. PARC Technical re-

port.

LOPES, CRISTINA VIDEIRA, & LIEBERHERR, KARL. 1994 (July). Abstracting Process-

to-Function Relations in Object-Oriented Applications. Pages 81–99 of: ECOOP

’94.

LOW, G.C., RASMUSSEN, G., & HENDERSON-SELLERS, B. 1996. Incorporation of

Distributed Computing Concerns into Object-Oriented Methodologies. Journal of

Object-Oriented Programming, 9(3), 12–20.

MAEDA, CHRIS, LEE, ARTHUR, MURPHY, GAIL, & KICSALES, GREGOR. 1997. Open

Implementation Analysis and Design. In: ACM Symposium on Software Reusability

(SSR).

MAES, PATTIE. 1987 (October). Concepts and Experiments in Computational Reflec-

tion. Pages 147–155 of: OOPSLA ’87 Proceedings.

MALONE, THOMAS W., & CROWSTON, KEVIN. 1994. The Interdisciplinary Study of

Coordination. ACM Computing Surveys, 26(1), 87–119.

MARTIN, JAMES, & MCCLURE, CARMA. 1988. Structured Techniques. Prentice-Hall.

MARTIN, ROBERT, RIEHLE, DIRK, & BUSCHMAN, FRANK (eds). 1997. Pattern Lan-

guages of Program Design 3. Addison-Wesley.

MARTINS, JOAO, & GIL, LUIS. 1996 (Setembro). Implementacao em C++ de uma Frame-

work para Concorrencia. Relatorio do Trabalho Final de Licenciatura em Engenharia

Informatica e de Computadores.

MATSUOKA, SATOSHI, & YONEZAWA, AKINORI. 1993. Analysis of Inheritance Anoma-

ly in Object-Oriented Concurrent Programming Languages. Pages 107–150 of:

AGHA, GUL, WEGNER, PETER, & YONEZAWA, AKINORI (eds), Research Directions

in Concurrent Object-Oriented Programming. MIT Press.

MCAFFER, JEFF. 1995 (August). Meta-level Programming with CodA. Pages 190–214

of: ECOOP’95.

212 BIBLIOGRAPHY

MCHALE, CIARAN. 1994. Synchronisation in Concurrent, Object-oriented Languages: Ex-

pressive Power, Genericity and Inheritance. Ph.D. thesis, Department of Computer

Science, Trinity College, Dublin.

MCHALE, CIARAN, WALSH, BRIDGET, BAKER, SEAN, & DONNELLY, ALEXIS. 1991.

Scheduling Predicates. Pages 177–193 of: TOKORO, MARIO, NIERSTRASZ, OSCAR,

& WEGNER, PETER (eds), Proceedings of the ECOOP’91 Workshop on Object-based

Concurrent Computing, vol. 612. Springer-Verlag.

MCHALE, CIARAN, WALSH, BRIDGET, BAKER, SEAN, & DONNELLY, ALEXIS. 1992.

Evaluating Synchronization Mechanisms: The Inheritance Matrix. Presented at E-

COOP’92 Workshop on Object-based Concurrency and Reuse.

MEIJLER, THEO DIRK, & NIERSTRASZ, OSCAR. 1998. Beyond Objects: Components.

Pages 49–78 of: PAPAZOGLU, MICHAEL, & SCHLAGETER, GUNTER (eds), Coopera-

tive Information Systems. Academic Press.

MESZAROS, GERAD, & DOBLE, JIM. 1997. A Pattern Language for Pattern Writing.

Pages 529–574 of: MARTIN, ROBERT, RIEHLE, DIRK, & BUSCHMAN, FRANK (eds),

Pattern Languages of Program Design 3. Addison-Wesley.

MUKHERJI, MANIBRATA, & KAFURA, DENNIS. 1995 (November). Specification of Multi-

Object Coordination Schemes Using Coordinating Environments. Tech. rept. Depart-

ment of Computer and Information Systems, University of Delaware, Newark.

MULET, PHILIPPE, MALENFANT, JACQUES, & COINTE, PIERRE. 1995 (October). To-

wards a Methodology for Explicit Composition of MetaObjects. Pages 316–330 of:

OOPSLA’95.

NEUSIUS, CHRISTIAN. 1991 (July). Synchronizing Actions. Pages 118–132 of: ECOOP

’91.

NIERSTRASZ, O. M. 1987 (October). Active Object in Hybrid. Pages 243–253 of: OOP-

SLA ’87 Proceedings.

BIBLIOGRAPHY 213

NIERSTRASZ, OSCAR. 1993. Composing Active Objects. Pages 151–171 of: AGHA, GUL,

WEGNER, PETER, & YONEZAWA, AKINORI (eds), Research Directions in Concurrent

Object-Oriented Programming. MIT Press.

NIERSTRASZ, OSCAR, & DAMI, LAURENT. 1995. Component-Oriented Software Tech-

nology. Pages 3–28 of: NIERSTRASZ, OSCAR, & TSICHRITZIS, DENNIS (eds), Object-

Oriented Software Components. Prentice-Hall.

PAPATHOMAS, MICHAEL. 1995. Concurrency in Object-Oriented Programming Lan-

guages. Pages 31–68 of: NIERSTRASZ, OSCAR, & TSICHRITZIS, DENNIS (eds),

Object-Oriented Software Components. Prentice-Hall.

PAPATHOMAS, MICHAEL. 1996 (November). ATOM: An Active Object Model for En-

hancing Reuse in the Development of Concurrent Software. Tech. rept. RR 963-I-LSR-2.

IMAG-LSR Grenoble, France.

PAPATHOMAS, MICHAEL, & NIERSTRASZ, OSCAR. 1991. Supporting Software Reuse

in Concurrent Object-Oriented Languages: Eploring the Language Design Space.

Pages 189–204 of: TSICHRITZIS, DENNIS (ed), Object Composition. Centre Universi-

taire d’Informatique, University of Geneva.

PARNAS, DAVID. 1978. Some Software Engineering Principles. Pages 237–247 of: Struc-

tured Analysis and Design: State of the Art Report. INFOTECH International.

PEREIRA, JOAO. 1994 (Setembro). Enriquecimento com Controlo de Concorrencia de Especi-

ficacoes Orientadas por Objectos. Tese de Mestrado/Master Thesis, Instituto Superior

Tecnico, Universidade Tecnica de Lisboa, Lisboa, Portugal.

PFISTER, CUNO, & SZYPERSKI, CLEMENS. 1996 (July). Why Objects Are Not Enough.

In: First International Component Users Conference (CUC’96).

RASMUSSEN, G., HENDERSON-SELLERS, B., & LOW, G.C. 1996a. An Object-Oriented

Analysis and Design Notation for Concurrency and Distributed Systems. Journal

of Object-Oriented Programming, 9(6).

214 BIBLIOGRAPHY

RASMUSSEN, G., HENDERSON-SELLERS, B., & LOW, G.C. 1996b. Extending the

MOSES Methodology to Distributed Systems. Journal of Object-Oriented Program-

ming, 9(4), 39–46,100.

REENSKAUG, TRYGVE, ANDERSON, EGIL P., BERRE, ARNE-JORGEN, HURLEN, ANNE,

LANDMARK, ANTON, LEHNE, ODD ARILD, NORDHAGEN, ELSE, NESS-ULSETH,

EIRIK, OFTEDAL, GRO, SKAAR, ANNE LISE, & STENSLET, PAL. 1992. OORASS:

seamless support for the creation and maintenance of object oriented systems.

Journal of Object-Oriented Programming, 5(6), 27–41.

REENSKAUG, TRYGVE, WOLD, PER, & LEHNE, ODD. 1996. Working With Objects: The

OOram Software Engineering Method. Manning Publications Co.

RIEHLE, DIRK. 1996 (December). Describing and Composing Patterns Using Role Dia-

grams. Pages 137–152 of: Proceedings of the Ubilab Confereence ’96.

RIEHLE, DIRK. 1997 (October). Composite Design Patterns. Pages 218–228 of: Conference

on Object-Oriented Programming Systems, Languages and Applications, Proceedings.

RIEHLE, DIRK, & GROSS, THOMAS. 1998 (October). Role Model Based Framework De-

sign and Integration. Pages 117–133 of: Conference on Object-Oriented Programming

Systems, Languages and Applications, Proceedings.

RM-ODP. 1995 (May). ITU-T Recommendation X.901 — ISO/IEC 10746-1 ODP Reference

Model Part 1. Overview. ISO/IEC JTC1/SC21/WG7, ISO/IEC Copyright Office,

Geneve, Switzerland.

RODDEN, TOM, & BLAIR, GORDON. 1991 (September). CSCW and Distributed Sys-

tems: The Problem of Control. Pages 49–63 of: Proceeding of the Second European

Conference on Computer-Supported Cooperative Work.

ROSA, FRANCISCO ASSIS, & SILVA, ANTONIO RITO. 1997 (July). Component Config-

urer: A Design Pattern for Component-Based Configuration. Pages 13–32 of: The

2nd European Conference on Pattern Languages of Programming, EuroPLoP ’97.

BIBLIOGRAPHY 215

ROSA, FRANCISCO ASSIS, & SILVA, ANTONIO RITO. 1998 (May). Functionality and

Partitioning Configuration: Design Patterns and Framework. Pages 79–89 of: IEEE

Fourth International Conference on Configurable Distributed Systems.

RUMBAUGH, JAMES, BLAHA, MICHAEL, PREMERLANI, WILLIAM, EDDY, FREDERICK,

& LORENSEN, WILLIAM. 1991. Object-Oriented Modeling and Design. Prentice-Hall.

RUPING, ANDREAS. 1996 (July). Framework Patterns. In: The 1st European Conference

on Pattern Languages of Programming, EuroPLoP ’96 (Washington University technical

report #WUCS-97-07).

SCHMIDT, DOUGLAS C. 1995. The ACE Object-Oriented Encapsulation of Lightweight Con-

currency Mechanisms. A white paper describing the ACE concurrency wrappers.

SELIC, BRAN, GULLEKSON, GARTH, & WARD, PAUL T. 1994. Real-Time Object-Oriented

Modeling. John Wiley and Sons.

SHETH, AMIT P., & LARSON, JAMES A. 1990. Federated Database Systems for Man-

aging Distributed, Heterogeneous, and Autonomous Databases. ACM Computing

Surveys, 22(3), 183–236.

SHLAER, SALLY, & J.MELLOR, STEPHEN. 1992. Object Lifecycles - Modeling the World in

States. Prentice-Hall.

SHRIVASTAVA, SANTOSH K., DIXON, GRAEME N., & PARRINGTON, GRAHAM D. 1991.

An Overview of the Arjuna Distributed Programming System. IEEE Software, Jan-

uary, 66–33.

SILVA, ANTONIO RITO. 1997a. A Quality Design Solution for Object Synchroniza-

tion. Pages 576–580 of: LENGAUER, CHRISTIAN, GRIEBL, MARTIN, & GORLATCH,

SERGEI (eds), Third International European Conference on Parallel Processing. Passau

Germany, August 1997. Proceedings. Springer-Verlag, LNCS 1300.

SILVA, ANTONIO RITO. 1997b (June 30-July 3). Framework, Design Patterns and Pat-

tern Language for Object Concurrency. Pages 1024–1033 of: CSREA International

Conference on Parallel and Distributed Processing Techniques and Applications.

216 BIBLIOGRAPHY

SILVA, ANTONIO RITO. 1998. Development and Extension of a Three-Layered Frame-

work. Chap. 27 of: ZAMIR, SABA (ed), Handbook of Object Technology. New York,

CRC Press.

SILVA, ANTONIO RITO, SOUSA, PEDRO, & MARQUES, JOSE ALVES. 1995 (December).

Development of Distributed Applications with Separation of Concerns. Pages 168–

177 of: IEEE Asia-Pacific Software Engineering Conference.

SILVA, ANTONIO RITO, PEREIRA, JOAO, & MARQUES, JOSE ALVES. 1996a (March). A

Framework for Heterogeneous Concurrency Control Policies in Distributed Appli-

cations. Pages 105–114 of: IEEE 8th International Workshop on Software Specification

and Design.

SILVA, ANTONIO RITO, HAYES, FIONA, MOTA, FRANCISCO, TORRES, NINO, & SAN-

TOS, PEDRO. 1996b (October). A Pattern Language for the Perception, Design and

Implementation of Distributed Application Partitioning. Presented at the OOPSLA’96

Workshop on Methodologies for Distributed Objects.

SILVA, ANTONIO RITO, PEREIRA, JOAO, SOUSA, PEDRO, & MARQUES, JOSE ALVES.

1996c (January). Atomicity Policies using Design Patterns. INESC Technical Report

AR/2/96.

SILVA, ANTONIO RITO, PEREIRA, JOAO, & MARQUES, JOSE ALVES. 1996d (July). Cus-

tomizable Object Synchronization Pattern. In: The 1st European Conference on Pat-

tern Languages of Programming, EuroPLoP ’96 (Washington University technical report

#WUCS-97-07).

SILVA, ANTONIO RITO, GALHARDAS, HELENA, SOUSA, PAULO, SILVA, JORGE, &

SOUSA, PEDRO. 1996e (July, 2-4). Designing Distributed Applications from an

Organisational Perspective. Pages 57–73 of: 4th European Conference on Information

Systems.

SILVA, ANTONIO RITO, ROSA, FRANCISCO ASSIS, & GONCALVES, TERESA. 1997a

(September). Distributed Proxy: A Design Pattern for Distributed Object Commu-

nication. In: The 4th Conference on Pattern Languages of Programming, PLoP ’97(Wash-

ington University technical report #WUCS-97-34).

BIBLIOGRAPHY 217

SILVA, ANTONIO RITO, PEREIRA, JOAO, & MARQUES, JOSE ALVES. 1997b. Objec-

t Recovery. Chap. 15, pages 261–276 of: MARTIN, ROBERT, RIEHLE, DIRK, &

BUSCHMAN, FRANK (eds), Pattern Languages of Program Design 3. Addison-Wesley.

SILVA, ANTONIO RITO, GONCALVES, TERESA, ROSA, FRANCISCO, BERRE, ARNE-

JORGEN, & AAGEDAL, JAN OYVIND. 1997c (October). Organization, Information

System and Distributed Modeling: An Integrated Approach. Pages 57–65 of: IEEE

First International Enterprise Distributed Object Computing Workshop.

SILVA, ANTONIO RITO, SOUSA, PEDRO, & ANTUNES, MIGUEL. 1998 (August). Nam-

ing: Design Pattern and Framework. Pages 316–323 of: IEEE 22nd Annual Interna-

tional Computer Software and Applications Conference.

SILVA, ANTONIO RITO, ROSA, FRANCISCO ASSIS, & GONCALVES, TERESA. 1999.

Framework Description Using Concern-Specific Design Patterns Composition.

ACM Computing Surveys, Symposia on Application Frameworks, 31(2).

SOUSA, PEDRO, SEQUEIRA, MANUEL, ZUQUETE, ANDRE, FERREIRA, PAULO, LOPES,

CRISTINA, GUEDES, PAULO, & MARQUES, JOSE ALVES. 1993. Distribution and

Persistence in the IK Platform: Overview and Evaluation. Usenix Computing Sys-

tems, 6(4).

STROUSTRUP, BJARNE. 1991. The C++ Programming Language. Addison Wesley.

THOMAS, LAURENT. 1994 (August). Inheritance Anomaly in Thrue Concurrent Object-

Oriented Languages: A Proposal. Pages 541–545 of: Proceedings of the IEEE TEN-

CON’94.

TOMLINSON, CHRIS, & SCHEEVEL, MARK. 1989. Concurrent Object-Oriented Pro-

gramming Languages. Pages 79–124 of: KIM, WON, & LOCHOVSKY, FREDERICK H.

(eds), Object Oriented Concepts, Databases, and Applications. ACM press, Frontier Se-

ries.

TOMLINSON, CHRIS, & SINGH, VINEET. 1989 (October). Inheritance and Synchroniza-

tion with Enabled-Sets. Pages 103–112 of: OOPSLA ’89 Proceedings.

218 BIBLIOGRAPHY

TOMLINSON, CHRIS, SCHEEVEL, MARK, & KIM, WON. 1989. Sharing and Organiza-

tion Protocols in Object-Oriented Systems. Journal of Object-Oriented Programming,

2(4), 25–36.

VLISSIDES, JOHN. 1995. Unidraw: A Framework for Building Domain-Specific Graph-

ical Editors. Pages 239–290 of: LEWIS, TED (ed), Object-Oriented Application Frame-

works. Manning.

VLISSIDES, JOHN, COPLIEN, JAMES, & KERTH, NORMAN (eds). 1996. Pattern Languages

of Program Design 2. Addison-Wesley.

WEGNER, PETER. 1987 (October). Dimensions of Object-Based Language Design. Pages

168–182 of: OOPSLA ’87 Proceedings.

WEGNER, PETER. 1992. Dimensions of Object-Oriented Modeling. Computer, 25(10),

12–20.

WEIHL, WILLIAM. 1989. Local Atomicity Properties: Modular Concurrency Control

for Abstract Data Types. ACM Transactions on Programming Languages and Systems,

11(2), 249–282.

WEIHL, WILLIAM. 1993a. The Impact of Recovery in Concurrency Control. Journal of

Computer and System Sciences, 47(1), 157–184.

WEIHL, WILLIAM. 1993b. Transaction-Processing Techniques. Pages 329–352 of: MUL-

LENDER, SAPE (ed), Distributed Systems - Second Edition. Addison-Wesley.

WEINAND, ANDRE, GAMMA, ERICH, & MARTY, RUDOLF. 1988 (September). ET++ -

An Object-Oriented Application Framework in C++. Pages 46–57 of: OOPSLA ’88

Proceedings.

WIRFS-BROCK, REBECCA, WILKERSON, BRIAN, & WIENER, LAUREN. 1990. Designing

Object-Oriented Software. Prentice-Hall.

YONEZAWA, AKINORI, SHIBAYAMA, ETSUYA, TAKADA, TOSHIHIRO, & HONDA, YA-

SUAKI. 1987. Modelling and Programming in an Object-Oriented Concurrent Lan-

guage ABCL/1. Pages 55–89 of: YONEZAWA, AKINORI, & TOKORO, MARIO (eds),

Object-Oriented Concurrent Programming. MIT Press.


Recommended