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.