Compaq ACMS for OpenVMS
Writing Applications


Previous Contents Index

5.1.3 Passing Workspaces

This section presents the rules for passing ACMS workspaces to and from a task you call from another task.

ACMS allows a called task to accept arguments in the form of task workspaces. User-written agents or tasks may pass workspaces to other tasks.

Note

The rules for passing workspaces when you call the task from an agent are the same as the rules for passing workspaces when you call the task from another task. See Compaq ACMS for OpenVMS Systems Interface Programming for information on writing an agent program.

A task passes workspaces to a called task by position. That is, the contents of the first workspace identified by the USING phrase in the parent task is moved to the first workspace named in TASK ARGUMENTS clause in the called task, and so on, for each workspace named in the USING phrase. This is the same as the method for passing workspaces to routines in procedure servers or to DECforms forms.

When calling a task, ACMS compares the length of each workspace to be passed with the length of the corresponding workspace in the called task. If any do not match, ACMS cancels both the parent and the called task. However, if you transpose two workspaces of the same length, ACMS does not flag this reversal.

Warning

When the task-call-task feature is used, it is possible to see the following error in SWL:


ACMSWSP-E-NONESUCH, INTERNAL ERROR: SPECIFIED BLOCK DOES NOT EXIST 

This error could be the result of declaring a workspace in the child task, but not using it. If the workspace is not used, remove the declaration from the child task and remove the workspace from the workspace list in the task call in the parent task.

A called task can accept arguments using task workspaces only. You cannot pass arguments into group, user, or system workspaces. Special rules apply for accessing group, user, and system workspaces in called tasks.

You can omit a workspace when you call a task. If you do, ACMS initializes the workspace in the called task with its default contents from the CDD workspace definition stored in the task database (.TDB file). If there are no default contents, ACMS initializes the workspace with zeros.

You can specify READ, WRITE, or MODIFY access for each workspace you include in a TASK ARGUMENT clause. Use MODIFY for passing and returning data, READ for passing data, and WRITE for returning data:

Specifying READ access on task workspace arguments can provide performance benefits for tasks calling other tasks, because ACMS does not have to update the workspace in the parent task when the called task completes.

In creating workspaces for task calls, bear in mind the trade-off between workspace size and the various access types. For large workspaces, it is more efficient to pass data using a READ workspace and return data using a WRITE workspace than it is to pass and return data in a single MODIFY workspace. Conversely, it is more efficient to pass a single MODIFY workspace containing a small amount of data than it is to pass several separate READ and WRITE workspaces.

You may specify any workspace type (task, user, group, or system) as an argument and pass it to the called task with the USING phrase. However, note that the parent task may supply only workspaces to task workspaces in the called task. See Section 5.1.3.2 for further information on accessing group and user workspaces.

5.1.3.1 Using System Workspaces

Each task instance owns its own copy of each of the three ACMS system workspaces. Once a called task instance starts, these copies are totally independent of a parent task.

Normally, you do not pass a system workspace from a parent task to a called task. Instead, move the data you need from the system workspace into a task workspace, and then pass it. You can move data by using either a MOVE clause or a processing step.

If you find you must pass a system workspace to a called task, specify READ access in the TASK ARGUMENT clause. This protects the contents of the system workspace from accidental modification.

The following rules apply to the three ACMS system workspaces when they are passed by default to a called task:

5.1.3.2 Handling User and Group Workspaces

A called task can access the same group and user workspaces that a parent task can access. You must be careful when updating group and user workspaces shared by a parent and called task, because it is possible to overwrite data and store incorrect results.

If both parent and called tasks require only read access to a user or a group workspace, then you can write both tasks as you normally do. However, because ACMS updates only the master copies of user and group workspaces at the end of a task instance, you must consider the case where either the parent task or the called task must update a user or group workspace that both tasks reference and use.

Note

If a parent and called task access the same workspace for update by using the WITH LOCK clause, ACMS cancels the called task.

When a parent and a called task both attempt to update the contents of a user or group workspace, the following occurs:

  1. The called task completes and ACMS updates the master copy of the workspace.
  2. The parent task completes and ACMS updates the master copy of the workspace, thereby overwriting the previous contents stored by the called task.

Data from the called task can be lost this way.

The best method of handling a group or user workspace is to pass the workspace from a parent task into a task workspace of the same layout in the called task (see Example 5-5). This way, when the parent task completes, the master copy of the user workspace updates correctly. This method is also more efficient than having each called task individually access the user workspace.

5.1.3.3 Tasks You Also Select from a Menu

You must give special consideration to accessing group and user workspaces in tasks that can be selected from a menu and that can also be called by other tasks.

You can test whether the task is being initiated by a menu or called from another task. If it is being called from another task, move the user or group workspace you want to use into a task workspace of the same layout. Example 5-5 illustrates a technique that you can use to implement this functionality.

When a task is initiated by a menu selection, ACMS initializes any TASK ARGUMENT clause workspaces with their initial CDD contents or zeros. In order for both a menu and another task to call it, the called task should check the selection method and then transfer the contents from the appropriate workspace (see Example 5-5).

Another method is to write a task that is selected from the menu and that calls the other task. Example 5-4 illustrates this technique. You write a dummy task, the only function of which is to call the other task from the menu, thereby avoiding the problem.

5.1.3.4 Example of Updating Group and User Workspaces

Example 5-4 and Example 5-5 illustrate how to use group and user workspaces with called tasks when the parent, the called task, or both need to update a group or user workspace.

Following is an excerpt from the task group definition used in Example 5-4 and Example 5-5:


WORKSPACES ARE 
    TASK_WSP1, 
    TASK_WSP2, 
    USER_WSP WITH TYPE USER; 
   .
   .
   .
TASKS ARE 
    PARENT_TASK: TASK DEFINITION IS PARENT_TASK; 
    CALLED_TASK: TASK DEFINITION IS CALLED_TASK; 
END TASKS; 
    .
    .
    .

If a parent task requires that a called task update a user or group workspace, pass the workspace into a workspace in the called task defined as a TASK ARGUMENT WITH ACCESS MODIFY. When the called task completes, ACMS updates the workspace in the parent task. When the parent task completes, ACMS updates the master copy of the user workspace.

Example 5-4 Updating User and Group Workspaces

DEFINE TASK PARENT_TASK 
 
USE WORKSPACES 
    TASK_WSP1, 
    USER_WSP WITH UPDATE LOCK; 
    . 
    . 
    . 
 
PROCESSING 
    CALL TASK CALLED_TASK USING 
        TASK_WSP1, 
        USER_WSP; 
    . 
    . 
    . 
 
END DEFINITION; 
 
 
DEFINE TASK CALLED_TASK 
 
USE WORKSPACES 
    TASK_WSP1, 
    TASK_WSP2, 
WORKSPACE IS 
    USER_WSP; 
TASK ARGUMENTS ARE 
    TASK_WSP1 WITH ACCESS MODIFY, 
    USER_WSP WITH ACCESS MODIFY; 
    . 
    . 
    . 
 
PROCESSING 
    CALL UPDATE_PROCEDURE USING 
        TASK_WSP1, 
        TASK_WSP2, 
        USER_WSP; 
    . 
    . 
    . 
 
END DEFINITION; 

Note that the called task defines the workspace named USER_WSP as a task-owned, task instance workspace and not as a user workspace. This definition allows the called task to use the same record layout as that of the workspace when it is defined in the group as a user workspace.

If you need to select CALLED_TASK (shown in Example 5-5) from an ACMS menu as well as to call CALLED_TASK from PARENT_TASK, the technique of passing the user workspace as a TASK ARGUMENT does not work. Because the task is selected from a menu, ACMS initializes the TASK ARGUMENT workspace with its CDD initial contents or with zeros. For both a menu and another task to call it, the called task should check the selection method and then transfer the contents from the appropriate source.

Example 5-5 Passing User Workspaces to Menu Tasks

USE WORKSPACES 
    TASK_WSP1, 
    TASK_WSP2, 
    USER_WSP; 
WORKSPACE IS 
    USER_WSP WITH NAME USER_WSP_COPY; 
TASK ARGUMENTS ARE 
    TASK_WSP1, 
    USER_WSP_COPY; 
 
BLOCK WORK 
PROCESSING 
    NO PROCESSING; 
    SELECT FIRST TRUE 
        ( ACMS$L_CALL_SEQUENCE_NUMBER <> 0 ): 
            MOVE USER_WSP_COPY TO USER_WSP; 
    END SELECT; 
  .
  .
  .
PROCESSING 
    CALL update_procedure USING 
        TASK_WSP1, 
        TASK_WSP2, 
        USER_WSP; 
  .
  .
  .
END BLOCK WORK; 
ACTION IS 
    SELECT FIRST TRUE 
        ( ACMS$L_CALL_SEQUENCE_NUMBER <> 0 ): 
            MOVE USER_WSP TO USER_WSP_COPY; 
    END SELECT; 
 

In Example 5-5, when the task is selected from a menu, the task uses the contents of the user workspace. If another task calls the task, the first processing step copies the user workspace data passed by the parent task into the user workspace declared in this task. At the end of the block, the ACTION clause employs a MOVE phrase to update the copy of the user workspace that the parent task passed as a task workspace argument.

If the ACMS$L_CALL_SEQUENCE_NUMBER is not 0, you know that the task was called by another task, and not initiated using a menu selection.

5.1.4 Controlling Called Tasks

This section describes various mechanisms for controlling tasks that are called by other tasks. You can pass control information in a workspace that you define, use the EXIT task clause, or test ACMS system workspace fields.

5.1.4.1 Passing Control Information in User-Defined Workspaces

In some cases, a called task needs to know information about the parent task. For example, a called task may need to record the name of each task that calls it, or it may need to perform different processing steps, depending on the task that called it. Suppose that you want to pass only a few fields from a system workspace to a called task. The most efficient method is to use the MOVE clause to transfer the data from the system workspace to one or more fields in a task workspace supplied to the called task.

Example 5-6 illustrates how a parent task can pass workspaces to a called task.

Example 5-6 Passing Data to a Called Task

WORKSPACES ARE 
    DATA_WSP1, 
    DATA_WSP2, 
    DATA_WSP3; 
 
BLOCK WORK 
    .
    .
    .
PROCESSING 
    CALL PROC_1 USING 
        DATA_WSP1, 
        DATA_WSP2; 
    MOVE ACMS$T_TASK_NAME TO PARENT_TASK_NAME, 
        "BATCH_JOB_1.COM" TO ACMS$T_SELECTION_STRING; 
    .
    .
    .
PROCESSING 
    CALL TASK B USING 
        DATA_WSP1, 
        DATA_WSP2, 
        DATA_WSP3; 
    .
    .
    .
PROCESSING 
    CALL PROC_2 USING 
        DATA_WSP2, 
        DATA_WSP3; 
 
END BLOCK WORK; 
    .
    .
    .
WORKSPACES ARE 
    DATA_WSP1, 
    DATA_WSP2, 
    DATA_WSP3; 
 
TASK ARGUMENTS ARE 
    DATA_WSP1 WITH ACCESS READ, 
    DATA_WSP2 WITH ACCESS MODIFY, 
    DATA_WSP3 WITH ACCESS WRITE; 
 
BLOCK WORK 
    .
    .
    .
PROCESSING 
    CALL PROC_3 IN SVR1 USING 
        DATA_WSP1, 
        DATA_WSP2, 
        DATA_WSP3; 
    .
    .
    .
PROCESSING WITH NO IO 
    DCL COMMAND IS "SUBMIT 'P1" IN SVR2; 
    .
    .
    .
END BLOCK WORK; 

In this example, Task B:

  1. Accepts one set of data items for ACCESS READ into DATA_WSP1
  2. Accepts another set of data items for ACCESS MODIFY into DATA_WSP2
  3. Returns a group of data items in the workspace DATA_WSP3, defined with ACCESS WRITE.

The name of the parent task is passed to the called task in a field named PARENT_TASK_NAME in the DATA_WSP1 workspace. Task A copies the name of the current task into that field with the MOVE clause. It uses the DATA_WSP1 workspace, because that workspace is defined in the TASK ARGUMENTS clause for READ access only.

This example also illustrates one method of loading data into the workspace for use by the called task. In this case, Task B uses the ACMS$SELECTION_STRING workspace to submit a batch job using a DCL server. ACMS always passes the contents of the ACMS$SELECTION_STRING system workspace from the parent task to the called task. ACMS parses each element of the ACMS$SELECTION_STRING workspace and assigns the elements to the DCL parameter. The first element is assigned to P1, the second element is assigned to P2, and so on.

The technique of moving one or two fields from a system workspace into a task instance workspace is more efficient than supplying the entire ACMS$TASK_INFORMATION workspace to the called task. Not only do you pass one less workspace to the called task, but the called task does not require as much space in the task instance workspace pool.

5.1.4.2 Ending a Called Task

A task can end by exiting normally or by canceling itself. In either case, you can return one of the default ACMS task status codes or a status code that you define.

To exit from a task normally, use the EXIT TASK clause. The EXIT TASK syntax allows a task to complete with a success status value other than that which produces the default "Task completed normally" message (ACMS$_TASK_COMPLETE). If the EXIT TASK clause returns a status, it must be a success status.

You can use the CANCEL TASK clause to cancel a task from within a task definition. If the CANCEL TASK clause returns a status, it must be a failure status. You can specify a failure status value other than that which produces the default "Cancel results from a step action in the task definition" message (ACMS$_TASK_DEF). See Example 5-7.

Example 5-7 Returning Your Own Exit and Cancel Status Values

PROCESSING 
  CALL STORE_NEW_CUSTOMER USING  
      CUST_RECORD; 
  SELECT FIRST TRUE 
      (TASK_STATUS = "OK"): 
        EXIT TASK RETURNING APPLMSG_CUST_ADDED; 
      (TASK_STATUS = "DUPL"): 
        CANCEL TASK RETURNING APPLMSG_DUPL_CUST; 
  END SELECT; 

In this example, APPLMSG_CUST_ADDED returns a success status value that you define, and APPLMSG_DUPL_CUST returns a cancel error status that you define.

When a called task exits, ACMS commits any active recovery unit (if there is no recovery-unit command) and returns the final status value to the parent task, as well as the contents of any workspaces defined as TASK ARGUMENTS for MODIFY or WRITE access. A called task can use this method to return information to the parent task to subsequently control the execution of that task.

When a called task is canceled, ACMS rolls back any active recovery unit (if there is no recovery-unit command). If the canceled task is retaining context in a server and you have defined a cancel routine for the server in the task group, ACMS runs the cancel routine. If the parent task BLOCK STEP has a CANCEL ACTION clause, ACMS executes that command. If a task cancels for any reason, only the cancel reason status code is returned to the parent task. The contents of any workspaces defined as TASK ARGUMENTS for MODIFY or WRITE access are not returned.

5.1.4.3 Controlling Parent Tasks

Once you have called a task, you can control subsequent execution of the parent task by using either the fields in task workspaces modified by the called task or the called task's final completion status. You can easily obtain the called task's final completion status by using the symbolic message code support in ADU.

For example:


PROCESSING 
  CALL TASK ENTER_ORDER; 
  ACTION IS 
    SELECT FIRST TRUE OF 
       ( ACMS$L_STATUS = ACMS$_CALL_CANCELLED ): 
           GOTO STEP SUBMITTER_CANCEL; 
       ( ACMS$L_STATUS = ACMS$_OPR_CANCELLED ): 
           GOTO STEP OPERATOR_CANCEL; 
    END SELECT; 
   .
   .
   .

In this example, a called task returns a bad status to the parent task. Instead of canceling the task, ACMS evaluates the SELECT FIRST clause in the ACTION step to determine whether the task was canceled by the user or by an operator.

5.1.5 Defining Local Tasks

You can define a task as LOCAL or GLOBAL. GLOBAL tasks can be either selected from a menu or called from another task. LOCAL tasks can only be called from another task.

GLOBAL is the default task type. You can select a GLOBAL task from a menu or with the SELECT command in CP, or you can call or chain to a GLOBAL task from another task. However, you can access LOCAL tasks only by calling or chaining to them from another task.

Define a LOCAL task when you want to:

You cannot override the LOCAL/GLOBAL task attribute by using a task group definition, if you define the task in a separate task definition.

5.1.6 Mixing I/O Methods in Parent and Called Tasks

ACMS allows a called task to use a different I/O method than that of the parent task. For example, a task using DECforms I/O can call tasks that use terminal I/O in DCL servers or ACMS stream I/O as well as other DECforms I/O tasks.

In order for a task using DECforms or terminal I/O to call a task using stream I/O, the user-written agent must associate a stream ID with a submitter ID. Note that the ACMS CP performs this association automatically. For more information on agents, streams, and submitted IDs, see Compaq ACMS for OpenVMS Systems Interface Programming.

Although you can associate a stream ID with a submitter ID, you cannot associate a terminal device specification with a stream ID. Therefore, if an agent calls a task defined to use stream I/O, the called task can only call or chain to other stream I/O tasks or tasks that do not perform I/O. If an agent calls a task defined to use stream I/O, that task cannot call a task that performs local requests, remote requests, or terminal I/O from a server.

A similar rule also applies to tasks that do not perform I/O and are, therefore, defined WITH NO I/O. Because no I/O information is passed to the task when an agent calls it, a NO I/O task may only call or chain to other NO I/O tasks.


Previous Next Contents Index