Progress
Language Tutorial
for Windows


Sharing with Persistent Procedures

The persistent procedure is different from parameters and SHARED resources, in that it makes an entire procedure context available to other modules.

It is important to remember that persistent procedures instantiate separate, individual contexts—not one large context in which each context becomes a part of the whole. By using the procedure HANDLE your code can make the separate procedures interact with each other.

The point of the persistent procedure is that what is available to be shared between modules is now under your control. The resources in a persistent procedure can be loaded and unloaded in bulk.

Persistent Procedure Syntax

The first step in creating a persistent procedure, is to define a HANDLE variable to hold the context reference as the following code fragment shows:

DEFINE VARIABLE proc-handle AS HANDLE. 

The next step is to run an external procedure with the PERSISTENT option of the RUN statement. The diagram below shows the relevant RUN statement syntax.

SYNTAX
RUN extern-procedure
  [ PERSISTENT [ SET handle ] ] [ runtime-parameters ] 

Progress sets the HANDLE variable you supply to the handle for the procedure context.

This code fragment shows a valid persistent procedure call:

RUN lt-12-02.p PERSISTENT SET proc-handle. 

When you are through with a procedure, you need to delete it. This is the syntax for the DELETE PROCEDURE statement.

SYNTAX
DELETE PROCEDURE proc-handle 

Here is an example of the delete procedure statement:

DELETE proc-handle NO-ERROR. 

There are some other 4GL language elements that help you manage persistent procedures. Table 12–1 describes them.

Table 12–1: Language Elements Used with Persistent Procedures
Element
Description
SESSION:FIRST-PROCEDURE
Use the FIRST-PROCEDURE attribute of the SESSION system handle to find the first persistent procedure in the current chain.
SESSION:LAST-PROCEDURE
Use the LAST-PROCEDURE attribute of the SESSION system handle to find the last persistent procedure in the current chain.
handle:FILE-NAME
Use the FILE-NAME attribute of a HANDLE variable to access the name of the external file that was used to create the procedure’s context. FILE-NAME can be one way to identify a particular context if only one copy of the context can be running at a time.
handle:PRIVATE-DATA
Use the PRIVATE-DATA attribute of a HANDLE variable to store additional information about the procedure. For example, PRIVATE-DATA can be used in conjunction with FILE-NAME for procedures that can be run several times to uniquely identify each instance (context) of that procedure.
handle:NEXT-SIBLING
Use the NEXT-SIBLING attribute of a HANDLE variable to find the next persistent procedure in the current chain. If NEXT-SIBLING is null, then the current procedure is the last procedure.
handle:PREV-SIBLING
Use the PREV-SIBLING attribute of a HANDLE variable to find the previous persistent procedure in the current chain. If PREV-SIBLING is null, then the current procedure is the first procedure.
VALID-HANDLE
Use the VALID-HANDLE function to check if a HANDLE variable is a valid reference to a current persistent context.
THIS-PROCEDURE
Use the THIS-PROCEDURE system handle to access the handle of the current context.

Persistent Procedure Programming Example

Follow the steps below for a demonstration of persistent procedures.

  1. Open lt-12-01.p and run it. The display shown below appears:
  2. Choose Run Procedure 2. An alert box appears informing you that the context for procedure 2 is available. This alert box represents the body of an internal procedure stored in an external procedure file. The internal procedure was accessed and run from the main procedure after the execution of the external procedure was already complete.
  3. Choose Check Contexts. The filenames of all persistent procedures appear in the display.
  4. Choose Delete Context 2 and then choose Check Contexts again. The deleted context disappears from the list.
  5. Choose Exit, and then press SPACEBAR to return to the Procedure Editor.

The code for the main procedure is on the next page. The two external procedures are simply MESSAGE statements inside internal procedures:

lt-12-01.p
      /**********  DEFINE WIDGETS  **********/
/*1*/ DEFINE VARIABLE h-pp2 AS HANDLE.
      DEFINE VARIABLE h-pp3 AS HANDLE.
      DEFINE VARIABLE h-proc AS HANDLE.
            .
            .
            .
      /**********  DEFINE TRIGGERS  **********/
      ON CHOOSE OF b-pp2-on DO:
/*2*/      IF NOT pp2-cnxt THEN DO:  
/*3*/          RUN lt-12-02.p PERSISTENT SET h-pp2. 
/*4*/          pp2-cnxt = VALID-HANDLE(h-pp2).
               DISPLAY pp2-cnxt WITH FRAME Frame1.   
           END.
/*5*/        RUN p-message IN h-pp2.
       END.
      ON CHOOSE OF b-pp2-off DO:
/*6*/      DELETE PROCEDURE h-pp2 NO-ERROR. 
          pp2-cnxt = VALID-HANDLE(h-pp2).
           DISPLAY pp2-cnxt WITH FRAME Frame1.      
       END.
              .
              .
              .
/*7*/    ON CHOOSE OF b-num-cnxt DO:   
          File-list = "".
         h-proc = SESSION:FIRST-PROCEDURE.
         REPEAT WHILE VALID-HANDLE(h-proc).
              File-list = File-list + " " + h-proc:FILE-NAME.
              h-proc = h-proc:NEXT-SIBLING. 
         END.  
        DISPLAY File-list WITH FRAME Frame1.
      END.   
/*8*/    ON CHOOSE OF b-exit DO:      
          IF pp2-cnxt THEN DELETE PROCEDURE h-pp2.     
          IF pp3-cnxt THEN DELETE PROCEDURE h-pp3. 
          APPLY "WINDOW-CLOSE" TO CURRENT-WINDOW.
        END. 
       /**********  MAIN LOGIC  **********/ 
      DISPLAY pp2-cnxt pp3-cnxt WITH FRAME Frame1.
      ENABLE ALL WITH FRAME Frame1.
      WAIT-FOR WINDOW-CLOSE OF CURRENT-WINDOW. 

The points below help explain the code:

  1. The HANDLE variables hold the pointers to the persistent procedures.
  2. This IF statement prevents the user from establishing many separate contexts for each procedure.
  3. The PERSISTENT option asks Progress to save the procedure, and the SET option provides the handle to the procedure.
  4. The VALID-HANDLE function takes a HANDLE variable and determines if it is a legal reference to a current persistent procedure.
  5. This RUN statement uses the IN handle syntax to access and run an internal procedure in the persistent procedure context.
  6. The DELETE PROCEDURE statement removes the procedure.
  7. This trigger runs through the current chain of persistent procedures and records the filenames of each in a string.
  8. The exit trigger makes sure the procedures are destroyed before exiting the procedure. Because you stored the procedure HANDLE when you ran the procedure, you have programmatic control of that procedure. In this example, you use that HANDLE to explicitly delete any surviving procedure contexts before exiting the main procedure.

Copyright © 2004 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095