| Version 1.9 Build 1367
|
|
Next: Control Hub
Up: Note 186: The Tasking Environment of AIPS++
Previous: Overview
Subsections
The clients of a distributed object may only manipulate the object through its
interface. To express the interface, we use a subset of C++ and the AIPS++ class
library. It must be emphasized that the objects can be manipulated from
languages other than C++, and can be implemented in languages other than C++.
An alternative strategy would be to describe the interfaces other than C++,
such as the language neutral ``IDL.'' Using C++ however has a couple of
advantages:
- 1.
- Many people already know it, so it makes for one less language to
learn.
- 2.
- AIPS++ has developed documentation tools which can parse C++
header files.
The following rules are to be followed when defining a distributed
object. While these rules may appear restrictive to the C++ programmer, they
are chosen to reduce difficulties in providing a bindings to other
languages.1, or to alleviate confusion for
end users (case should not be considered).
- An interface is described by a pure-abstract base class. (All
member functions are virtual, with no defined implementation).
- No global functions or overloaded symbols (``operator+''), are to
be used.
- Only single inheritance is supported.
- All member function names (including those which are inherited)
must be unique and case-insensitive.2
- Parameters to functions must be one of the following types:
- Scalar
- Char, uChar, Short, uShort, Int, uInt, Float,
Double, Complex, DComplex, and String. Scalars
may be passed by value or by reference.
- Index
- An index is an integral type which is used to
specify a position in a data structure. Its value is adjusted by
the run-time system to be zero or one-relative, depending on what
the native language requires An Index should be pased by value or
reference, an IPosition by reference or const reference. (The
canonical representation of an Index is 1-relative).
- Record
- The Record class or a known structure may be
passed by reference or const reference, and returned by value. ``A
known strcuture'' is a pure aggregation of scalar, array, and
record types, for example:
struct real_grid {
Array<Float> data;
Vector<Float> origin, increments;
};
Only predefined structures may be used, they may not be created at
will. Note that a particular language binding might just use a
general Record type rather than providing all the structure types.
- ObjectID
- An ObjectID is a unique identifier which is
used by the run-time system to uniquely identify a particular
object. The ObjectID is opaque, however it may be mapped
int, and retrieved out of, a String. An ObjectID is either
valid or invalid. ObjectID's may be compared for equality.
- ObjectType
- An object type is an opaque type which is
interconvertible with strings. The only operations which
are available are:
- 1.
- Exact comparison of type.
- 2.
- Determining if one type is a direct or indirect
parent of the other.
The ObjectType of any valid ObjectID may be obtained through
the language binding.
- Array
- Multi-dimensional arrays of scalar type (including
Index) are allowed. Only Arrays of dimension one may be used for
types Record, ObjectID, and ObjectType. Array, Vector, Matrix
and Cube of the above scalar types. Vector, Matrix, or Cube may
be substituted for Array to indicate the required
dimensionality. Arrays must be passed by reference or const
reference, and returned by value.
- Object Reference
- An ObjectRef<Class> may be passed
as an argument to a function by reference, const reference, or by
value. Passing the object by value indicates that the object
might make use of the object at a later time. Passing it by
reference indicates that only temporary use of the Object is being
made. An ObjectReference is either valid, or it is null.
The run-time system is responsible for canonicalizing the data types
(so, for example, integers are converted between little-endian and
big-endian systems, and for Index values are modified to be appropriate
to a given language binding).
- The return type of a function can either be ``void'', or it can
return by value any of the types which are allowed as function
parameters.
After an object reference is obtained by a client process, it's member functions
(``services'') may be invoked by the client process.
When an object reference is no longer needed it should be released3. An
object reference can be queried to determine whether or not it is valid
(attached to an object server).
Most language bindings will provide two methods of invoking the objects member
functions.
- Stub Interface
- This is the interface which is most ``natural'' for any
particular language binding. For example, in C++ it corresponds to invoking
the member functions of the class.
- Dynamic Invocation Interface
- 4 With
this interface an argument list is marshalled, a function is named, and a
request for service is sent to the object server. While this interface is
generally less convenient it has two advantages over the usual stub
interface:
- 1.
- It allows the services of any object to be invokes, not only those
which have been ``compiled into'' the client.
- 2.
- Typically the stub interface will be synchronous, the DII will
usually have an asynchronous mode of operation.
The Dynamic Invocation Interface might often be made available through an
``any'' object.
An execution of a service from an object may return normally, or it might
result in an exception. An exception might be thrown by the object if it is
being used improperly, or it might be thrown by the run-time system to signal
a failure (for example, an object server crash). The exception mechanism is
part of the language binding. To facilitate this binding, the possible
exceptions are limited to the following:
- ConnectionError
- A communications error, probably either a network
outage or a crash of a process.
- HubError
- An error in the internal workings of the control hub (a hub
crash would result in a ConnectionError).
- ArgumentError
- An invalid argument (type or value) was given to an object
implementation.
- ObjectError
- All other errors from the object implementation.
Each exception has three strings associaged with it:
- 1.
- An informative error message.
- 2.
- A string which describes the originator of the exception.
- 3.
- A (possibly blank) relative URL (described below in section xxxx) which contains additional help information.
All object classes must be derived from a base class (distributed_object). This is done to ensure that all objects have a
common set of services, primarily to allow the objects to function
well in a GUI environment.
class distributed_object {
public:
Record help() const; // 1
Record interface() const; // 2
Bool save_state(String file_name); // 3
Bool restore_state(String file_name); // 4
};
The member functions fulfill the following purposes:
- 1.
- Distributed objects may be directly manipulated by end users,
so it is important that a uniform method of obtaining help is
available. The exact mapping to the Record is still
undetermined, but generally speaking it will provide both
per-class and per-method documentation.
- 2.
- This member is provided so that a GUI control for any distributed
object can be provided. Again, the exact mapping is not
decided, but there will be an entry per member function
(inclduing arguments and return types).
- 3.
- This member is provided to implement a simple form of
persistence and so that the user can save the state of his
environment. AIPS++ core classes are expected to save their
state into AIPS++ table objects.
- 4.
- This is used by the object to restore its state.
Next: Control Hub
Up: Note 186: The Tasking Environment of AIPS++
Previous: Overview
  Contents
Please send questions or comments about AIPS++ to aips2-request@nrao.edu.
Copyright © 1995-2000 Associated Universities Inc.,
Washington, D.C.
Return to AIPS++ Home Page
2006-03-28