The logic in this example is straight forward. The Control Queues guard the counters and
Element array. Writes always succeed, add an Element to the channel, and increment the
write count. Reads will succeed so long as there are Elements in the channel (readCount
< writeCount); otherwise the read blocks until an Element is added.
There are a couple of important points to note here. First, the logic is clear and platform
independent since it relies solely on the facilities provided by the MASCOT Machine.
Second, all of the synchronization is in one place and not distributed through the
application. The corollary to this is that if the MASCOT Machine works so will the
application; it is essentially another expression of the virtual machine concept.
A MASCOT Machine creates applications based on SET documents. SETs define entities
(activities, channels, pools, devices, and subsystems and the connections between them)
in an implementation independent way. It is the machine’s job to interpret SETs and build
applications that execute on the machine’s host. For a static machine this is done at
compile time; for dynamic machines the process happens at run time, is more complex,
and has a number of steps. In both cases, however, the basic process is know as
‘incarnation’ and entails marshalling the resources needed to run the entities defined by a
SET.
The incarnation process starts by reading and parsing one or more SET documents. In
MASCOT terminology, the SET is enrolled. This results in a collection of templates that
represent the SET in an implementation dependent way. For those entities that require
an implementation (IDAs, activities, and devices), the machine maps MASCOT names in
an implementation specific way; the entity-maps section of a SET document controls how
this is done. In the case of Java and other OO languages, MASCOT names map to
classes; mapping in other systems will take a different form.
Although all MASCOT entities are defined in a SET they can only be incarnated within the
context of a subsystem. The act of incarnating a subsystem and all of its contents (which
may include other subsystems) is called ‘forming’ the subsystem. The result of forming a
subsystem is an incarnation that can be ‘started’. The machine guarantees that all of a
subsystem’s contained entities are incarnated before it can be started. A subsystem may
be incarnated any number of times (a machine may impose implementation dependent
limits) and the machine will manage each incarnation separately. Under certain
circumstances incarnations may be pooled and reused but this requires care to ensure
that resources are released properly.
A MASCOT Machine always creates the global subsystem when it boots. For static
machines it contains incarnations of the other subsystems that make up the application.
In dynamic machines, the global subsystem is initially empty. If a newly enrolled SET
adds an activity to the global subsystem then the new activity is incarnated and run in the
global context. This behavior is mechanism by which the applications bootstrap
themselves. The pattern is to add an activity to the global subsystem that loads further
SET documents and then starts the application’s baseline subsystems.
Along with Control Queues and their associated primitives, all MASCOT Machines also
implement the following scheduling primitives:
•start
Start a subsystem incarnation. In the static machine case the subsystem
incarnation will be predefined. Dynamic machines can load, incarnate, and start
new subsystems.
•suspend
Issued by activities and causes a scheduling pass. In bare systems suspend is
implemented by the machine itself. In a hosted environment the machine will
map this to the underlying system.