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.