One of the key features of the Zim Application Model is that it supports “event driven” applications. That is, it includes applications where several windows can be open at the same time and where the user can select the window with which to interact. Therefore, the Framework must track open windows, dispatch events to the correct program that manages each window, and enable the sending of events from one process/program to another.
To support this type of application, the Application Framework includes a Process Manager. Within the Framework, each program associated with an open window is considered to be a “process” and the function of the Process Manager is to keep track of current processes.
Note: These are not processes in the sense that the term is often used in operating systems. However, these programs do have the characteristic of being run at any time (i.e. when the user decides to interact with the associated window). This characteristic is similar to that of operating system processes.
Application programs access the facilities of the Process Manager by calling specific programs in the Framework such as pRegisterProcess, pUnRegisterProcess, pProcessManager, and pDispatchAction.
A window and program that are to be managed by the Process Manager must obey the following rules:
- The main procedure of the program must be of the form
Procedure ThisProgram (out vlStatus, in vlAction)
The program has two parameters. The first is an output parameter in which any return codes are placed. The Framework does not look at this return value. The second parameter is the name of an input action.
- The program should be organized so that it processes the action and then returns. The code in the Simple Event Loop and Main Window is a good example of this organization. The names of the actions and what happens for each is entirely up to each program.
- Each program, when it first starts processing (usually when it opens its associated window) must call pRegisterProcess. It is this call that makes the Process Manager aware of the program. There are several ways that this can be done. For example, on entry, a program can check to see if its window is open. If it is not open, it could proceed to execute a WINDOW OPEN and then call pRegisterProcess.
- An alternative is to have the window opening and the call to pRegisterProcess triggered by passing a specific initialization action to the program.
- The Framework requires that windows have identical window names and tags. As a result, in the following discussion, we use the terms window name and window tag interchangeably.
The major operations associated with a process are
- process registration
- task management
- stopping a process
- dispatching actions
- message passing and the message queue
Every program to be managed by the Process Manager must register itself. Registration is done by calling pRegisterProcess. A call to pRegisterProcess provides the Process Manager with several vital pieces of information including the name of the window with which the program is associated and the name of the program itself. Registering the window and program creates a “process” in the Process Manager.
The Framework provides a program called pTaskManager that displays the current processes being managed by the Process Manager and also enables you to switch to any of those processes.
Stopping a Process
When a specific window is being closed by the program that is managing the window, the program must inform the Process Manager that the process no longer exists. This is done by calling pUnRegisterProcess. This can be seen in the Simple Event Loop and Main Window example.
As we saw in the examples in Application Design, every application has a main event loop that gets the next action and then sends (dispatches) it to the correct program. Dispatching the action is usually done by calling pDispatchAction. pDispatchAction is passed an action name and the window name for which the action is intended. The Process Manager looks up the window name, finds the name of the program associated with that window (remember that this information was passed in pRegisterProcess), and calls that program.
Message Passing and the Message Queue
Usually applications operate by getting an action, dispatching it, and processing it. Each action is dealt with immediately. However, this is not always the case. For example, a typical window for doing data entry handles SAVE (write out modified data in the window to the database) and EXIT (close the window) actions. When an EXIT action is to be processed, the program would normally check to see if the data in the window has been modified. If it has changed, the program would want to arrange to have a SAVE action to be performed before the EXIT action. In other cases, a specific action can be implemented as a sequence of other actions.
To handle these situations, the Framework implements a Message Queue which contains actions. It also provides programs (such as pPostActionQueue and pActionQueue) that enable application programs to inspect the queue, insert items at the end of the queue, and insert items at the front of the queue.
Note: The Message Queue is both a queue and a stack.
pGetAction (see the Using Event and Action Mapping example), which translates user interface events into actions, is integrated with the Message Queue. Before doing a FORM INPUT, it checks to see if the queue is empty. If it is not, the next action in the queue is returned. If you make explicit use of the Message Queue, you must use pGetAction to get the next action.
Actions can be sent directly to a process, bypassing the Message Queue. pSendAction is used for this purpose. When you call pSendAction, the target process immediately processes the action and then control returns to the original program that called pSendAction.