FW Profile - C1 Implementation
Procedure Implementation

The FW Profile uses the name "Procedure" for the entity which in UML is represented as an Activity Diagram.

Thus, procedures can be used to model a sequential flow of conditionally executed actions.

The C1 Implementation represents a procedure through a procedure descriptor (PRD). A PRD is a data structure which holds all the information required to describe a procedure. Users do not normally manipulate the PRD directly. Instead, they manipulate the pointer to the PRD which is defined as an instance of type FwPrDesc_t. Its internal structure is described in FwPrPrivate.h. Most applications are not concerned with the internal structure of a PRD and can ignore this header file.

Applications manipulate a procedure by passing its PRD to the functions defined by the C1 Implementation. Thus, for instance, an application executes a procedure through the following function call: FwPrExecute(prDesc). Here, prDesc is the PRD of the procedure to be executed.

Procedure Modules

The implementation of the procedure concept consists of several modules as described in the table:

Module Description Files
Core Provides an interface to start, stop, and execute a procedure. FwPrCore.h, FwPrCore.c
DCreate Provides an interface to create a new PRD. The functions in this module are simple to use but rely on dynamic memory allocation. Applications which wish to avoid dynamic memory allocation can use the alternative SCreate module. FwPrDCreate.h, FwPrDCreate.c
SCreate Provides macros to instantiate a new PRD (without using dynamic memory allocation) and functions to initialize it. This module is alternative to the DCreate module. FwPrSCreate.h, FwPrSCreate.c
Config Provides an interface to configure a newly created PRD by defining its nodes and control flows. FwPrConfig.h, FwPrConfig.c

The DCreate and SCreate modules are normally alternative to each other (but deployment of both in the same application is possible). Applications which are severely constrained in memory can instantiate and configure the PRDs of their procedures by directly manipulating their internal fields. This requires a detailed understanding of the internal structure of the PRD but allows an application to dispense with both the DCreate/SCreate modules and with the Config module. An example of direct instantiation and configuration of a PRD is provided in FwPrMakeTestPR2Dir.

Procedure Actions and Guards

The procedure actions and guards are defined as function pointers of type, respectively, FwPrAction_t and FwPrGuard_t. Applications must provide functions of these two types to implement the actions and guards of their procedures. Both the guard and the action functions are called with the PRD as an argument.

Note that, if a procedure uses the same action or the same guard more than once, the associated function pointer is only stored once in the PRD.

Procedure Data

The PRD includes a field holding a pointer to the procedure data. The procedure data are data which are manipulated by the procedure actions and guards. The exact type of the procedure data is defined by applications for each procedure. In most cases, it will take the form a struct whose fields represents the inputs and outputs for the procedure actions and guards. The PRD treats the pointer to the procedure data as a pointer to void. Functions FwPrSetData and FwPrGetData allow this pointer to be set in, and be retrieved from a PRD.

Error Checking

The procedure functions perform a limited amount of error checking. If they find an error, this is reported through the error code which stores the identifier of the last error encountered by the implementation. The value of the error code can be read with the FwPrGetErrCode function. Nominally, the error code should be equal to prSuccess. If this is not the case, the behaviour of the procedure is undefined.

Thread Safety

The functions defined by the C1 Implementation do not use any global data. They operate exclusively on the data passed to them as arguments. They are therefore inherently thread-safe.

Basic Usage

The basic usage of a procedure instance within an application is as follows:

  1. The procedure descriptor is created. This is most conveniently done using the FwPrDCreate.h module but may also be done using the FwPrSCreate.h module (if it is desired to avoid use of dynamic memory allocation).
  2. The data upon which the procedure operates is loaded into the procedure by means of function FwPrSetData.
  3. The procedure is configured by means of the add* functions in the FwPrConfig.h module which allow an application to define the nodes and the control flows of the procedure.
  4. The configuration of the procedure may be checked through function FwPrCheck.
  5. The procedure is started with function FwPrStart.
  6. The procedure is executed with function FwPrExecute.
  7. The procedure is stopped with function FwPrStop.
  8. If the procedure descriptor was created using the FwPRDCreate.h module, the memory allocated to the procedure may be released with function FwPrRelease.

Examples of creation and configuration of procedures can be found in file FwPrMakeTest.c. Examples of operation of a procedure can be found in file FwPrTestCases.c or in the Demo Application.

Procedure Extension

The C1 Implementation supports an extension mechanism for procedures which is similar to the inheritance-based extension mechanism of object-oriented languages.

A procedure (the base procedure) can be extended to create a new procedure (the derived procedure). A derived procedure can either be created dynamically with the FwPrCreateDer function or else it can be instantiated statically with macro FW_PR_INST_DER and initialized with function FwPrInitDer.

After being created, a derived procedure is a clone of its base. It can then be configured by: overriding its actions (through function FwPrOverrideAction) or overriding its guards (through function FwPrOverrideGuard).

The internal structure of the PRD is designed to minimize the memory requirements of derived procedures. A PRD is split into two parts: the Base Descriptor and the Extension Descriptor (see FwPrPrivate.h module). The Base Descriptor holds the information about the procedure topology (its nodes and their connections) whereas the Extension Descriptor holds the information about the procedure actions and guards. During the extension process, only the Extension Descriptor is duplicated whereas the Base Descriptor is shared between a procedure and its children. This significantly reduces memory occupation in a situation where a large number of procedures are derived from the same base procedure. The internal structure of a procedure descriptor is shown in the figure.

PRDExtension.png
P&P Software GmbH, Copyright 2011, All Rights Reserved