Each data object has a unique capability (tag) id, and one or more tag descriptor structures. These descriptors are stored in other data objects (also identified using tags) called environments. Both the data object itself and/or the tag descriptors may be replicated across processor nodes in a system. Objects may also be referred to by name, an ASCII character string (of limited length -- currently 64 characters total) instead of by tag. At runtime a tag may be obtained by finding the object with the given name. The naming convention allows for the inclusion of environment names, and both absolute (starting with the separator character / ) and relative :
obj-name , or
env-name/obj-name, or
env-name/env-name/.../obj-name, or
/obj-name , or
/env-name/env-name/.../obj-name
In an analogous manner, it is possible to absolutely specify the location of a data object using a sequence of environment tags, starting (implicitly) in the system environment. This is commonly used internally in MagicEight instead of the ASCII absolute name.
In order for a tag to be resolved, a tag descriptor structure for it must be found, either in the current environment or in any parent environment up to and including the ever-present system (or root) environment. These descriptors may be duplicated, or exported, allowing other processes to access them (given proper permission).
A common example of such duplication is used to make the naming system work. Each environment contains not only a tag descriptor for itself (named .index) but also a tag descriptor for its parent (appropriately named .parent). And each environment is represented by tag descriptor in its parent environment. Duplicate tag descriptors (such as the three tags representing an environment containing another) are linked into a doubly linked list using absolute capabilities.
Each process begins with a separate environment, located in the system environment, which is used to store the data and instruction object descriptors used solely within that process.
If a data or instruction object is to be shared between processes, it is typically moved into the System (or top level) environment, where it may be easily accessed by tasks from other processes (allowing shared data and instruction objects.) Another feature of objects described in the system environment (outside of process environments) is that they are persistent -- they are not automatically deallocated upon the completion of their creating process.
In a distributed system such as MagicEight, the data objects accessed by a task must be clearly identified, in order to ensure the availability of the data local to a processor when the task is executed. Unlike a program executing in a single address space, there are no ubiquitous globals. There are three lists of data elements accessible by the instructions of a given task, each with a different role :
All of the data objects referred to in a task's parameter lists must be located in memory local to the processor, with appropriate permissions, before a task will be scheduled for execution.
Each task is provided with a list of Input parameters, which may be either constants or tags referring to input and output data objects for the task. These parameters are the major component of the data structure that represents a task waiting to be executed, the task token. Input parameters are accessed by the instruction sequence using the recommended function argument passing mechanism for the machine executing the task.
Object Addressing Methods
The Internal parameters are provided to allow a task instruction to access private data objects, not available to the calling task ( i.e. protected procedures.) The parameters must be tags, and are resolved in an environment specified by the Internal parameter list. It may be the Process enviroment of the program calling it, or a different one. If a parameter tag isn't resolved by the specified environment, the System environment is searched.
The access mechanism for Internal (and Private) parameter tags is still being decided. The parameter tags are resolved by the runtime system prior to a task token being scheduled for execution, into pointers to local data structures.
Since the Internal parameters are bound to the task instructions, and not any particular instance, they must be shared by all callers of a task. While this is useful if a task such as a system-wide memory manager is desired, the more common approach to shared libraries requires support for internal parameters which are unique to each instance of a shared library of tasks. Such support is provided by Private parameters. These parameters allow a task to access data objects which are unique to a particular process, yet not accessible (read or write) by that process. The result is analogous to the ability to generate a new, protected type of object in an object oriented system. They are identified by a specially typed tag passed as an Input parameter. This tag does not give it's possesor any access priviledges to the data object (the Private parameter list). In order to access a Private parameter list, a task must provide a valid key to unseal the list. This key, stored local to appropriate tasks, is specified by the task that originally created the sealed parameter list.
Tags in both the Input parameters and the Internal parameters may be specified when building a parameter list for another task using the offset into the parameter list (negative in the case of Internal parameters.) When the task is posted, the system will copy the appropriate tags into the data structure.