Concurrency, which used to be the privilege of highly specialized application domains - operating systems and network programming - now rears its head in many traditional areas. Multi-threading, in particular, is of interest to ever more applications. Yet the techniques used to program concurrent applications remain low-level, as illustrated for example by widely used multithreading libraries. The resulting applications are difficult to produce, to debug and to maintain; the code is complex, relying on low-level notions such as semaphores. There is a stunning gap between the object-oriented concepts that are increasingly popular for the architecture of sequential programs and the techniques used for handling the multithreaded or concurrent parts.
The SCOOP mechanism seeks to remove this gap by bringing to the world of concurrency the same systematic O-O development techniques that have made their mark in the sequential world.
SCOOP starts from the observation that the basic framework of object-oriented computation lends itself naturally to a concurrent extension. Objects are independent entities with their own state and controlled access to their mechanisms. Contrary to most other approaches to concurrent O-O programming, we do not attempt to make objects "active", an approach that quickly lead to contradictions such as the "inheritance anomaly". Instead, SCOOP makes explicit the notion of processor, implicit in usual views of computation. Programs apply actions to objects using processors:
In sequential programming there is only one processor, and concurrency is defined by the presence of several allowing interleaved execution of instructions. These processors are threads of control; they can be computers ("processors") in the hardware sense, but also processes or threads on an operating system. To write a SCOOP program, one need not know how processors are actually implemented; the correspondence between the abstract architecture and the actual processors, software -or hardware- based, is described by a Concurrency Control File (CCF) independent from the rest of the application.
The following figure illustrates this architectural decision: the SCOOP level provides the general mechanisms that all SCOOP programmers will use. The lower level provides "handles", each based on a certain concurrency mechanism implementing its own view of processors and the associated facilities.
All calls to operations on a particular object are handled by a single processor; we say that the processor handles the object. With these basic concepts, we may isolate the difference between sequential and concurrent computation down to a single key point: what happens in the basic operation of O-O computation, a "feature call" of the form
To distinguish between synchronous and asynchronous calls, the program must specify whether the processor handling x is the same or another. This leads to the single language extension required by SCOOP: separate declarations. If x represents an object handled by another processor, it will be declared (in Eiffel syntax) not as
For simple reasons of being able to reason about programs, calls on a separate object are exclusive: only one client can use a separate supplier at a time. The mechanism for reserving an object is simply argument passing: a call of the form
the element retrieved by the last instruction is the one inserted by the first instruction. But some other separate client may have polluted the structure by squeezing in another insert instruction in-between, even though this is not reflected in the code. Such bugs are very difficult to identify because they are by their very nature transient - the problem will occur only rarely, and in appearance haphazardly. The SCOOP rules guarantee that the above calls may only occur in a routine of which x is a separate argument. So the intuitive expectation that the two calls act on the same object with no competing access in-between - as suggested by the code - indeed matches reality. If this property is not required, the calls to insert and value may just appear in different routines of the class, for a finer level of access control granularity.
The final synchronization mechanism is provided by a natural extension of the Design by Contract constructs of Eiffel. A precondition on a separate target, as in
These are the basic concepts of SCOOP. They are complemented by a few library mechanisms that tune the mechanism, for example to specify limits on the acceptable waiting time when trying to reserve an object.
The result is a general mechanism that makes it possible to program concurrent applications in a much simpler way than we have seen anywhere else. Check the numerous examples in the references below to see for yourself.