The architecture introduced in section iii raises a number of questions concerning the structure of applications, how services traditionally provided by servers or a kernel are provided, and how applications process their own exceptions.
In order to describe the inter-domain communciation system of Nemesis it is necessary to present some of the higher level constructs used in Nemesis to complement the single virtual address space approach. A full account can be found in . The key aspects are the extensive use of typing, transparency and modularity in the definition of the Nemesis interfaces and the use of closures to provide comprehensible, safe and extensive sharing of data and code.
Within the Nemesis programming model there are concepts of an interface reference, and an invocation reference, the latter being obtained from the former by binding. An interface reference is an object containing the information used as part of binding to build an invocation reference to a particular instance of an interface. The invocation reference will be a closure of the appropriate type and may be either a simple pointer to library code (and local state) or to a surrogate for a remote interface. In the local case an interface reference and invocation reference have the same representation - a pointer to a closure - binding is an implicit and trivial operation.
In Nemesis, as in Spring, all interfaces are strongly typed, and these types are defined in an . The used in Nemesis, called MIDDL, is similar in functionality to the s used in object-based RPC systems, with some additional constructs to handle local and low-level operating system interfaces. A MIDDL specification defines a single abstract data type by declaring its supertype, if any, and giving the signatures of all the operations it supports. A specification can also include declarations of exceptions, and concrete types.
The word object in Nemesis denotes what lies behind an interface: an object consists of state and code to implement the operations of the one or more interfaces it provides. A class is a set of objects which share the same underlying implementation, and the idea of object class is distinct from that of type, which is a property of interfaces rather than objects
When an operation is invoked upon an object across one of its interfaces, the environment in which the operation is performed depends only on the internal state of the object and the arguments of the invocation. There are no global symbols in the programming model. Apart from the benefits of encapsulation this provides, it facilitates the sharing of code.
In order to overcome the awkwardness that the lack of global symbols might produce (consider having to pass a reference to a memory allocation heap on virtually every invocation), certain interfaces are treated as part of the thread context. These are known as pervasives. The programming model includes the notion of the currently excuting thread and the current pervasives are always available. These include exception handlers, thread operations, domain control operations and the default memory allocation heap.
The programming model is supported by a linkage model. A stub compiler is used to map MIDDL type definitions to C language types. The compiler, known as middlc processes an interface specification and generates a header file giving C type declarations for the concrete types defined in the interface together with special types used to represent instances of the interface.
An interface is represented in memory as a closure: a record of two pointers, one to an array of function pointers and one to a state record. To invoke an operation on an interface, the client calls through the appropriate element of the operation table, passing as first argument the address of the closure itself.