Release 10.1A: OpenEdge Development:
Progress 4GL Handbook

> ## Using persistent procedures

> As you have seen in your work thus far, you can run one procedure from another. When you do this, you can pass `INPUT` parameters that are used by the procedure you run. When that procedure gets to the end of its 4GL code, it terminates and returns any `OUTPUT` parameters to the caller. This works the same for both external procedures (independent procedure source files) and for the internal procedures inside them.

> These procedures form a call stack. On top of the stack is the main procedure you run from the editor or from the OpenEdge startup command line. Below this is another procedure the main procedure runs, which in turn can run another procedure that is added to the stack, and so on. As each procedure terminates, it returns control to the procedure above it and is removed from the stack. All the resources it uses are freed up, and the procedure effectively disappears from the session unless it is run again. Figure 13–1 provides a rough sketch of how the procedure call stack can look.

> Figure 13–1: A procedure call stack

> In this example, `MainProc.p` runs `SubProc.p`. `SubProc.p` runs an internal procedure (`InternalProc`) inside it. While the Progress interpreter is executing code in `InternalProc`, the call stack looks like the diagram shown in Figure 13–2.

> Figure 13–2: Call stack in InternalProc

> What does this really mean? All three of these procedures have been instantiated and are currently in the session’s memory. What is actually in memory is the r-code for the procedure, which the interpreter understands, whether this was a `.r` file you previously compiled and saved or whether Progress has to compile the procedure on the fly at run time from its source code.

> It also means that all the elements that each procedure defines are currently in scope. Any variables, buffers, and other procedure objects have been instantiated along with the executable r-code. Progress has allocated the memory and other resources needed to execute them.

> It also means that control of the application flow is fairly rigid. The code in `MainProc.p` cannot do anything at all while `SubProc.p` is running. Likewise, the code in the main block of `SubProc.p` cannot do anything at all while `InternalProc` is running. The three procedures together form a single thread that cannot be interrupted except to cancel the whole program execution.

> When `InternalProc` returns to the rest of `SubProc.p`, any resources it defined, such as local variables, are freed up. `SubProc.p` can go on with the rest of its program logic. When `SubProc.p` returns to `MainProc.p`, all the resources allocated to it, including the in-memory copy of its executable code, are released and disappear. The code in `MainProc.p` has no way of accessing anything in `SubProc.p` except by receiving it back in the form of an `OUTPUT` parameter, because while `SubProc.p` is running, `MainProc.p` is completely blocked. When `SubProc.p` returns control to `MainProc.p`, it completely disappears.

> This is how generations of Progress 4GL applications (along with applications in many other languages) were written. A typical character-mode application has a top-level menu of some kind defined in the equivalent of `MainProc.p`. Depending on what the user requests, some subprocedure runs and the main procedure waits until it completes. A subprocedure can then run some additional subprocedure that performs a service for it. The result is a very hierarchical application, both in its physical construction and in its user-visible execution. To be sure, Progress developers have created very sophisticated techniques for allowing users to jump easily from one part of such an application to another with shortcut keys and the like, but these techniques mostly mask the inherent programming style of the language at that time. In the world of character screen applications without a mouse or much in the way of user-initiated events, and where all the user terminals are connected to a single host process that’s running the application itself and getting data from the database, this all works very well.

> But in a more modern application, written for a graphical environment, designed to be distributed between client user interface sessions and separate server sessions that control the database, with the need to communicate with a variety of devices and other applications and to make the user much more in control of the application flow than before, this programming style is not sufficient. It is for these reasons that Progress includes the many event-driven language constructs that you’ve been introduced to: object events, the `ON` `event``` statements, the `APPLY` statement, and so on.

> The procedures in your application have the same kinds of requirements that the visual objects you’ve worked with do. They must have greater flexibility in how they interact with each other, without depending on a rigid hierarchy of execution.

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