ParaSail has no global variables. So how does that work? Global variables have long been recognized as trouble makers in the software world, and they get much worse in a language with lots of parallelism. But can we eliminate global variables completely? ParaSail tries to do that by eliminating any notion of statically allocated variables. In C or C++, global variables are those marked
static or
extern, or in a language with modules/packages like Ada, global variables are those declared at the module level. Although their declaration might be hidden, such variables still represent global, variable state, and still create trouble.
In ParaSail,
interface modules are generic
types, and
class modules implement interfaces. That is, after providing generic parameters to an
interface, you end up with a
type. Any variable declared in a
class is what is often called an
instance variable, that is, there is one per object of the
type defined by the
class. There is nothing corresponding to what are called
class variables. In other words, the
variables declared in a
class will always be effectively fields/components of some enclosing object. You can of course also have
local variables inside the body of a procedure or function, but these are never statically allocated; they are stack-resident variables only (
automatic in C parlance).
So what do we have instead? In many cases, we simply substitute local variables declared in some relatively high-level procedure or function body, which are then passed (by reference) to other operations as parameters. In ParaSail, passing a variable as a parameter generally has
handoff semantics, meaning that it can't be simultaneously passed to multiple operations that might execute in parallel, nor can it be passed twice to the same operation as two different parameters (thereby eliminating certain kinds of
aliasing problems).
When it is necessary to have a data structure that can be accessible to multiple operations running in parallel, the data structure must be explicitly designed for concurrent access. In other words it must be a
concurrent data structure. In ParaSail, an interface may be specified as a
concurrent interface, and then all objects of a type defined by the interface support
concurrent access.
Containers represent a kind of middle ground, where the enclosing container might be designed for concurrent access, but the individual elements might not be, and so
handoff semantics would again apply to the individual elements.
There may be some concurrent interfaces that typically have exactly one object; that is they are typically
singleton interfaces. For example,
the file system, or
the database manager, or
the system clock. ParaSail provides a conceptual global singleton
Context interface for these, whose singleton object has one component for each such singleton interface, identified using the name of the interface. The
Context must appear as a parameter for operations that ultimately need access to one of these singleton interfaces, signifying that the operation has potential side effects on these singleton objects. It would always be preferable to pass in the actual singleton objects needed, but as a convenience, the
Context pseudo-object is available.
The
Context pseudo-object is provided as a parameter to the main entry point of a ParaSail application, so that it can gain access to these singletons and pass them on to callers. If an operation has a
Context parameter, and its caller also has a
Context parameter, then the caller's parameter is passed automatically to the operation if not specified explicitly. The
Context parameter may be read-only ("in") or read-write ("in-out"/"var"). Not surprisingly, the actual
Context parameter must be read-write if the formal is read-write.