Threading Rules that Affect Windows and ACCEPT Statements

There are a number of special rules that govern how and when threads can receive user input. In the following discussion, the phrase ACCEPT statement refers specifically to formats 1, 2, and 7 of the ACCEPT statement. These are the forms that retrieve the user's input.

When a thread attempts to execute an ACCEPT statement, two rules determine if that thread is allowed to proceed:

  1. The thread may proceed if no other thread is in an ACCEPT statement. This rule ensures that threads do not compete for a single piece of input. It prevents the possibility, for example, of alternate keystrokes going to different threads.
  2. The thread may proceed if the window in which the ACCEPT will occur is active, or if the active window is controlled by the current thread. A window is controlled by the thread that created it or the last thread that did an ACCEPT statement in it. A window can be controlled by only one thread at a time. This rule ensures that windows do not activate arbitrarily.

If an ACCEPT does not meet both of these conditions at the time that it would normally execute, its thread is suspended. The thread will remain suspended until both conditions are met (at which time the thread resumes and the ACCEPT executes).

Note: Even if the thread is suspended and the ACCEPT is not started, the ACCEPT may still be timed out with ACCEPT BEFORE TIME. It can also be terminated with a message, if ACCEPT ALLOWING MESSAGES is specified.

These rules apply only if there is more than one thread. If a suspended thread becomes the only remaining thread, then it automatically resumes execution.

If a thread suspends due to rule (2), it will suspend forever unless its window becomes active. This can happen in one of two ways: (a) another thread activates the window, or (b) the user activates the window. Arranging for the latter is much more common. It is the case where you want to give the user the ability to work in multiple windows at once, freely switching between them.

To create windows that the user can activate at will, you describe the windows as MODELESS when you create them. A modeless window allows the user to activate another window (the other type of window, called modal, does not allow the user to activate another window). When the user activates a modeless window, by clicking on it or using the host's method, the runtime generates a CMD-ACTIVATE event. In a single-threaded program, the program must detect this event and ACCEPT something in the appropriate window in order to activate that window. In a multithreaded program, there is a second option. To use this option you code your program in such a way that each modeless window runs in a separate thread, and you use the phrase LINK TO THREAD or BIND TO THREAD when you create each window. This phrase instructs the runtime to handle the CMD-ACTIVATE events on its own. In this arrangement, when a CMD-ACTIVATE event occurs, the runtime suspends the current thread and activates the new window. The thread controlling the newly active window then resumes execution. Technically speaking, the thread running the ACCEPT in the newly active window can leave the suspended state because it meets rules (1) and (2) described above.

This automatic runtime handling allows you to easily manage multiple windows. Each window is contained in a thread that need only manage that one window. The threads do not need to be aware of each other or know which window is active. If the threads have some need to communicate among themselves, they can do so with messages. See Thread Communication for more information.

Here is an example. The following program presents a maintenance screen for a data file. It also pops-up a window that has a list of all the records in the file. The user can update a record on the maintenance screen, and can select records from the list. When the user selects a record, the maintenance screen is updated with the selected record.

MAIN-LOGIC.
   PERFORM INITIALIZE
   DISPLAY STANDARD GRAPHICAL WINDOW, 
      LINK TO THREAD
   PERFORM THREAD SEARCH-THREAD, 
   PERFORM UNTIL DONE
      PERFORM DISPLAY-RECORD
      ACCEPT MAINTENANCE-SCREEN 
         ALLOWING MESSAGES FROM LAST THREAD
         ON EXCEPTION
            IF KEY-STATUS = W-MESSAGE
                PERFORM SAVE-CURRENT-RECORD
                RECEIVE RECORD-NUMBER 
                        FROM LAST THREAD
            END-IF
      END-ACCEPT
   END-PERFORM
   PERFORM SHUT-DOWN
   STOP RUN.

SEARCH-THREAD.
   DISPLAY FLOATING GRAPHICAL WINDOW,
      MODELESS, LINK TO THREAD
      HANDLE IN H-SEARCH-WINDOW
   PERFORM DISPLAY-SEARCH-LIST
   PERFORM UNTIL 1 = 0
      PERFORM ACCEPT-SEARCH-LIST
      SEND RECORD-NUMBER-SELECTED TO LAST THREAD
   END-PERFORM.

This example shows how using threads can simplify managing multiple windows. In it, one thread manages the main window, and one manages the search window. The search window is very simple, its thread sits in an infinite loop fetching a list item from the user and sending it to the main thread. The main thread sits in a loop accepting the main screen. If a message arrives from the search thread, it saves the current record and retrieves the record sent from the search window. By using multiple threads, each piece of your window-handling code stands alone. If it were written as a single-threaded program, the two loops accepting the windows would have to be combined into a single loop, with a state variable tracking which window is currently active.

Tip: The use of modeless windows and threads to provide the ability to switch between screens by pressing Taskbar buttons is demonstrated in an AcuBench sample project located in the Support area of the Acucorp Web site. To download the project, go to: https://supportline.microfocus.com/examplesandutilities/index.aspx, and select ACUCOBOL-GTĀ® Samples > Graphical User Interface (GUI) Sample Programs > Threadds.zip.