Perhaps
the most dominant metaphor in object-oriented
design is what we have called the client/server model
in
sections [theme] and [contracts].
This model is supported by the notion of contracts
as initially introduced for the language Eiffel.
Not accidentally, the client/server model is also
an important paradigm in distributed programming,
and hence may serve as a good starting point from which
to explore the possible contribution of object
orientation to distributed and concurrent programming.
A contract (as introduced in section [contracts])
describes the interface of an object and specifies the duties
and benefits for a client in terms of (logical) pre- and
post-conditions.
Active objects
-- distributed programming
- client/server model
- network-based computing
- heterogeneous systems
slide: Active objects
A similar specification may be used to describe the interaction
between a client and a server in a distributed environment.
In such an environment, a server is generally
a process waiting for some request from a client.
When such a request is received, the server spawns off
a process to handle the transaction with the client
and then continues to wait for requests.
Often, in addition to waiting for requests,
a server has responsibility of its own.
For example, in the case of a printer server,
the server needs to check whether the printers
to which it is coupled are still in operation.
In abnormal situations, a server may hold the requests
until the situation is restored to normal.
Despite the server's own activity,
for a client a server is just an entity
offering a collection of services.
Hence, as observed in [Meyer93], logically
the distinction between active and passive
objects
need play no role.
Operationally, however,
the distinction between passive
and active objects should be clear.
A passive object
uses the processing resources of the caller
to execute the method invoked,
whereas an active object possesses its own
processing resources to deal with the request.
Consequently, the implementation language must provide
constructs which allow the programmer to deal
(either implicitly or explicitly)
with the concurrency issues involved.
Which primitives are needed depends upon several factors,
among which is the choice of a particular
concurrency model
(suiting the application domain in question).
Given the availability of wide and local area networks,
it seems likely that complex systems
will become increasingly distributed in nature
and, hence, active objects will be the rule
rather than an exception.
An important consequence of the accessibility of networks,
in conjunction with the growing size of systems,
is that (large) systems will tend to become
more and more heterogeneous.
For example, multi-media systems are usually not built
as a single monolithic program,
but rather consist of a number of smaller cooperating
components, that may in their turn rely on third party
software to actually display the (multimedia) documents.
Concurrent problem solving
From a modeling perspective, the availability of
processes may lead to a more flexible,
not to say natural, approach to problem solving.
Having a notion of processes (or active objects)
at one's disposal, may lead to employing
the inherent concurrency characteristics
of a problem domain to arrive at a more natural
(that is intuitively suitable) model.
Problem solving
-- concurrency
- pipe-line concurrency
- divide and conquer
- cooperative problem solving
slide: Concurrent problem solving
Traditionally, three patterns of concurrent
problem solving can be distinguished,
which may be characterized
as pipe-line concurrency,
divide and conquer, and
cooperative problem solving.
See slide [6-c-p-s].
Pipe-line concurrency
may be used to
apply a sequence of filters sorting out
a good solution.
A well-known example of this kind of concurrency
is the implementation of the sieve of Eratosthenes
as a (dynamically growing) sequence of communicating processes,
each testing for divisibility by a prime number.
As a remark, pipe-line concurrency is also
a well-known composition mechanism of the Unix operating
system, where it is used to connect programs
that each perform a specific operation on a stream
of (character-based) data.
Divide and conquer
is an almost equally well-established technique
of exploiting the parallelism inherent
in a problem solution.
The basic idea is to split a problem
into relatively independent subproblems
that may be solved in parallel.
This subdivision may be repeated recursively.
As an example of this approach,
think of a parallel implementation of a
sorting algorithm (for example mergesort)
which consists of splitting the list to be sorted
in two halves that may be sorted independently
before being merged.
Although this approach is straightforward,
actual speedup may be hard to achieve.
The final pattern (or paradigm)
may be characterized as cooperative problem solving.
However, this characterization actually begs the question.
In contrast to the two previous patterns,
which employ a regular structure of processes
(respectively a sequence for pipe-lining
and a tree structure for divide and conquer),
the process structure employed in cooperative problem solving
may be arbitrarily complex.
It is this kind of modeling we are interested in
when discussing object-based concurrency.
Actually, this kind of cooperation comes closer
to a peer-to-peer relation than
the master-slave relation characteristic for
the client/server model.
Hence, the notion of client and server
must be taken in a relative sense, as reversible roles.
As an aside, as an area in which cooperative processes
play an important role (as a modeling vehicle)
we may mention discrete event simulation,
which, historically, lies
at the root of object-oriented programming.