IBM
Contents Index Previous Next



General Purpose Operators


Introduction

The abstract data type IdNode described in this section introduces a number of operators that may be used to simplify an SDL system. The simplifications will give both reduced code size and higher speed of execution for your application, as well as make debugging easier. This ADT cannot be used in OS integrations or with Cmicro.

The operators may be grouped into two groups:

Caution!

Be very careful using these operators, as you will then not be designing true SDL systems.

If the SDL description is a goal in itself you should not use the operators. If the SDL system is just a means to obtain something else, an application for example, the operators may be very useful.

Type IdNode

This abstract data type becomes available by inserting the analyzer include:

/*#include 'idnode.pr'*/

This abstract data type file introduces three SDL sorts called PrsIdNode, PrdIdNode, and SignalIdNode in SDL. These sort correspond to the types xPrsIdNode, xPrdIdNode, and xSignalIdNode in C, which are used to represent the symbol table in the generated application. The symbol table, which is a tree, will contain the static information about the SDL system during the execution of the generated program.

Is is possible to refer to processes, procedures, and signals (among others) using the following the names:

yPrsN_ProcessName    or &yPrsR_ProcessName
yPrdN_ProcedureName  or &yPrdR_ProcedureName
ySigN_SignalName     or &ySigR_SignalName

where ProcessName, ProcedureName, and SignalName should be replaced by the name of the process, procedure, or signal with prefix, or by the name given to the unit in a #NAME directive. To obtain a name of a unit with prefix the directive #SDL may be used:

yPrsN_#(ProcessName)  or &yPrsR_#(ProcessName)

To avoid problems when separate generation is to be used, the &yPrsR_... syntax is recommended.

The #SDL directive is not always possible to use. It will look for an entity with the specified name in the current scope unit (where the #SDL directive is used) and outwards in the scope hierarchy. So, for example, if the reference for a process is to be used in a process defined in another block, a #SDL directive cannot be used for the referenced process. The name of the referenced process ought then to be given in a #NAME directive.

If separate generation is used there may be more problems to access these references. The variables will be defined in the compilation unit where the entity they represent is defined.

A reference is visible in the compilation unit (file) where it is defined and in all subunits to the unit, as a compilation unit will include the .h file of all its parent units.

Problems occur when we want to use a reference in a place where it is not visible, for example using an xPrsIdNode for a process defined in a separate block, in a process in another block. All references are, however, extern, which makes it possible for a user to introduce an appropriate extern definition (in a #CODE directive) himself in the compilation units where it is needed.

Example 555

/*#CODE
#HEADING
extern XCONST struct xPrsIdStruct yPrsR_ProcessName;
*/

To know the name of the referenced process, a #NAME directive ought to be used.

Note:

Such extern definitions introduce dependencies between otherwise independent compilation units. It is your responsibility completely to maintain these dependencies.

Available Operators

GetIdNode: PId -> PrsIdNode;

This operator takes a PId value and returns a reference to the PrsIdNode that represents the process type. PrsIdNode values are not useful for anything except as parameters to the operators discussed here.

Kill: PId -> PId;

The Kill operator can be used to stop another process instance. In SDL a process instance may only stop itself. This operator has exactly the same effect as if the process instance given as parameter executed a stop operation. The Kill operator always returns the value null.

KillAll: PrsIdNode -> Integer;

This operator takes a reference to an PrsIdNode representing a process type and will kill all the instances of the specified process type. The effect is the same as if all the instances executed stop operations. The operator returns the number of "killed" process instances.

FirstPId: PrsdNode -> PId;

See SucPId: PId -> PId; (next).

SucPId: PId -> PId;

This operator, together with FirstPId, are intended to be used to enumerate all process instances of the process type referenced by the PrsIdNode given as parameter to FirstPId. FirstPId should be given a reference to an PrsIdNode for a process type and returns the first (last created) process instance. SucPId should be given a PId value and will return the next PId for the given process type.

Note:

During the enumeration of the process instances, no action that stops any instance of the enumerated process type may be executed.

This means, for example, that the complete enumeration should take place in one transition and that Kill operations should not be used in the enumeration.

InputPortLength: PId -> Integer;

This operator returns the number of signals in the input port of the given process instance.

InputPortLength: PId, SignalIdNode -> Integer;

This operator returns the number of signals, of the signal type given as IdNode parameter, that are present in the input port of the given process instance. The SignalIdNode parameter should refer to a SignalIdNode that represents a signal or a timer.

NoOfProcesses: PrsIdNode -> Integer;

This operator should be given a reference to an PrsIdNode representing a process instance set and will return the number of active instances of this instance set.

IsStopped: PId -> Boolean;

The operator may be used to determine if a PId value refers to a process instance that is active or has executed a stop operation.

Broadcast: PrsIdNode, SignalIdNode, PId -> Integer;

This operator may be used to send one signal (without parameters) to each active process instance of a specified process instance set. The value of the third parameter, of type PId, will be used as sender in the signals. The result of the operator is the number of signals that are sent during this operation, i.e. the number of active process instances of the specified type.

Note:

When you use this operator you hide signal sending in an expression in, for example, a task. This will decrease the readability of your SDL description, and should be well documented, at least with a comment.

FreeAvailList: PrsIdNode -> Integer and PrdIdNode -> Integer and SignalIdNode -> Integer

Note:

The FreeAvailList operator has no meaning in the SDL Explorer. It can be used but will in the Explorer be a null action.

The operator takes a reference to an IdNode (of one of the three type above) that represents a process, a procedure, or a signal and returns the memory in the avail list for the specified IdNode to the free memory by calling the sctOS function xFree. The function xFree uses the C standard function 'free' to release the memory. The FreeAvailList operator requires thus that free really releases the memory in such a way that it can be reused in subsequent memory allocations. Otherwise the operator is meaningless.

FreeAvailList is intended to be applied for reusing memory allocated for processes, procedures, and signals used only during a start-up phase. If the system, for example, contains a process used only during start-up, that is, all instances of this process perform stop actions early during the execution and no more processes will be created later, then the memory for these instances can be reused.

Caution!

This operator should only be used as one of the last resorts in the process of minimizing the memory requirements of an application.

Connection to Monitor

In the trace output, operators like Kill and Broadcast will produce trace messages exactly in the same way as the equivalent Stop operation and the sequence of Output operations.


http://www.ibm.com/rational
Contents Index Previous Next