Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Implementing Coroutines in COBOL

Status
Not open for further replies.

dcptnapx

Programmer
Mar 3, 2003
5
IT
IMPLEMENTING COROUTINES IN COBOL

Coroutines are a simple, efficient and useful form of concurrent programming (although it is better defined as co-operative programming).

Coroutines are like routines but, while there is always a hierarchical relation among common routines in a program, coroutines are all equivalent between themselves.
During the transfer of control from a routine to a second rotutine the caller remembers his state of execution and, when the callee gives up, the caller resumes after the current instruction. On the contrary the callee always resumes at his start.
The peculiarity of coroutines is that, in the exchange of control between coroutines, each coroutine always resumes as a caller routine.

Coroutines are helpful when a complex process could be simplified by decomposition in two o more sub-processes connected by sequential files.
Then these sub-processes can be implemented in the form of coroutines exchanging a virtual sequential files. The files are virtual because the write and the read of the same record happen at the same time and no real file is required.

As an example, we can employ coroutines in place of the awkward "program inversion" of JSP methodology (Jackson Structured Programming). The processes derived from data structures are straightforth converted in coroutines connected by virtual sequential files, without compromising the isomorphisms between data structures and respective algorithms.

Coroutines, although very useful, are supported only by a limited number of programming languages because they require a complex stack management.
COBOL does'nt directly support coroutines, but their implementation is amazingly easy by the exploitation of PERFORM features.
The following program example is the simplest implementation of coroutines in COBOL.



IMPLEMENTATION

The program contains a MAIN and two coroutines, say PROCESS-A and PROCESS-B. The first coroutine makes three virtual writes, the second makes three virtual reads. Every transfer of control from PROCESS-A to PROCESS-B corresponds to a virtual write in PROCESS-A and a virtual read in PROCESS-B. Every tranfer of control from PROCESS-B to PROCESS-A is a request for a new record.
The records are implicitly represented by the whole memory shared by the two processes.

The transfer of control from PROCESS-A to PROCESS-B is obtained by:
Code:
         PERFORM ENTER-PROCESS-B THRU EXIT-PROCESS-B
The transfer of control from PROCESS-B to PROCESS-A is obtained by:
Code:
         PERFORM EXIT-PROCESS-B THRU ENTER-PROCESS-B

Note that the transfer of control, in both directions, is always achieved by performing the same labels but in inverted order. This may sound rather strange, but it conforms to COBOL standards. Note also that at the end of processes none of the THRU-label remains suspended.

Code:
01     main.
02         perform enter-process-a thru exit-process-a
03         goback
04         .
05
06     enter-process-a.
07     begin-process-a.
08         display '<<  1'
09         perform enter-process-b thru exit-process-b
10         display '<<  2'
11         perform enter-process-b thru exit-process-b
12         display '<<  3'
13         perform enter-process-b thru exit-process-b
14         .
15     exit-process-a.
16         .
17
18     enter-process-b.
19     begin-process-b.
20         display ' >> 1'
21         perform exit-process-b thru enter-process-b
22         display ' >> 2'
23         perform exit-process-b thru enter-process-b
24         display ' >> 3'
25         perform exit-process-b thru enter-process-b
26         .
27     exit-process-b.


Following are the displays produced by the example:
[/code]
<< 1
>> 1

<< 2
>> 2

<< 3
>> 3
[/code]

The follwing map represents the sequence of instructions execution, according to the row numeration in the previous example:

Code:
MAIN         01 02 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 03
PROCESS-A    .. .. 06 07 08 09 .. .. .. .. .. 10 11 .. .. .. .. 12 13 .. .. .. .. 15
PROCESS-B    .. .. .. .. .. .. 18 19 20 21 27 .. .. 18 22 23 27 .. .. 18 24 25 27

The machinery of virtual WRITE/READ can be used in structured instructions like IFs, EVALUATEs, PERFORMs (both forms in-line and off-line) as shows next example:


Code:
       main.
           perform enter-process-a thru exit-process-a
           goback
           .

       enter-process-a.
       begin-process-a.
           display 'start process-a'
           set process-on  to true
           perform varying i from 1 by 1 until i > 3
              display '<<  ' i
              perform enter-process-b thru exit-process-b
           end-perform
           set process-off to true
           perform enter-process-b thru exit-process-b
           display 'end   process-a'
           .
       exit-process-a.
           .

       enter-process-b.
       begin-process-b.
           display 'start process-b'
           perform until process-off
              display ' >> ' i
              perform exit-process-b thru enter-process-b
           end-perform
           display 'end   process-b'
           .
       exit-process-b.

This example produces this output:
Code:
          start process-a
          <<  0000000001
          start process-b
           >> 0000000001
          <<  0000000002
           >> 0000000002
          <<  0000000003
           >> 0000000003
          end   process-b
          end   process-a


Note as each coroutines have the same structure held by stand-alone unrelated writing and reading processes, although their executions are embedded.
It is simple to make a more complex net of coroutines where each node of the net is a coroutine receiving real inputs and/or virtual inputs from one or more coroutines and writing real outputs and/or one or more virtual outputs to the same number of coroutines.



WARNING: Some COBOL compilers may support non-ANSI compliant behaviours of the PERFORM statement. This may affect the correct working of coroutines.
For example, to assure the ANSI compliant behaviour, CA-Realia requires the NOCALL compiler directive and Micro Focus requires TRICKLE.
COBOL II and COBOL/390 do not require any measure.

 
Thats really cool. Its good to discover something like one can resume a para from where he left last time.

I have not tried the code but I suppose it must be giving same result as U have mentioned about cobol/390.

Somehow still I am not able to recall a real time situation where we can use this. Can anyone come up with good example ?

Thanks
devesh
 
Hi,

I prefer program inversion.
By the way, program inversion should be automatic done by a JSP precompiler, so what is the problem.

Manual talk about PERFORM ... THRU ..... :

Code:
The only necessary relationship between procedure-name-1 and procedure-name-2 is
that a consecutive sequence of operations is executed, beginning at the
procedure named by procedure-name-1 and ending with the execution of the
procedure named by procedure-name-2.

So in fact a smart compiler would say that it the perform used in the b-part is an empty perform.

Also:

Code:
Note: A PERFORM statement must not cause itself to be executed. Such a recursive
PERFORM statement can cause unpredictable results.

You are very near a problem with this source.

Regards,

Crox
 
Hi Crox,

I respect your preference for program inversion, but, while JSP methodology is a precious conceptual tool available to all programmers, unfortunately the JSP precompiler isn't.
Anyway the JSP itself suggests coroutines as a solution to structure clashes and considers program inversion only as a spare wheel.

In the quote you give (taken from IBM COBOL Language Reference manual)regarding PERFORM <procedure-name-1> THRU <procedure-name-2>:


The only necessary relationship between procedure-name-1 and procedure-name-2 is
that a CONSECUTIVE SEQUENCE OF OPERATIONS IS EXECUTED, beginning at the
procedure named by procedure-name-1 AND ENDING WITH THE EXECUTION of the
procedure named by procedure-name-2.


the reference to the &quot;consecutive sequence of operations&quot;, IMHO, don't refers to the geography of the program, rather to the temporal sequence of execution.
In fact, the quote itself specifies &quot;consecutive sequence ... is executed&quot;.

Moreover, although the PERFORM always assures that procedure-name-1> is entered, it cannot equally assure that <procedure-name-2> will be ever reached. The quote only states that the reaching of finishing line is ALWAYS under the programmer's responsibility, this regardless of the geography of the program.

So, IMO, the quoted phrase doesn't represent any threat.

The coroutine implementation I presented is only the simplest. There are more complex implementations that don't require a strange geography (south under north) nor a TRHU complement of PERFORM.
Actually, I use a complex implementation boxed in a copybook, with processes and pipes (virtual files) parametrized by REPLACING. This makes all simple, elegant, readable and permits to build large nets of coroutines.

Regards
Alessandro
 
Hi deveshjogal,

Coroutines in COBOL aren't not a theoretic speculation. Personally I've been using them for circa 15 years, since the times of IBM OS/VS COBOL.

Unfortunately for you, coroutines are useful especially in complex problems (fortunately), so it isn't easy to exhibit sensible examples showing the advantages.

An example of application is a COBOL macro expander (realised in COBOL).
This program has a lot of conflicting data structures. His implementation is a non linear net of 12 coroutines with 11 virtual files.

My advice is to consult this PDF document &quot;A Portable C++ Library for Coroutine Sequencing&quot;, easily reachable by Google, containing a wealth of examples. My suggestion is to look first at &quot;Filter for Telegrams&quot; example, with the warning that there is a difference between C++ and COBOL coroutines in that the formers are objects that can have multiple istances dynamically allocated, while the latters must be statically defined at compile time.

It is also useful to cast a glance to vol.1 of Knuth's &quot;The Art of Computer Programming&quot;.

Regards
Alessandro
 
Hi,

Suppose your customer has an optimizing compiler and you must deliver warning-free source? (warning: possible drop through ...)

Suppose during a structured walk through, people find your program not easy to maintain?

Suppose you need a second or a third coroutine?

The construction looks very much like Italian food.

A real JSP programmer has of course his own precompiler. It is not difficult at all to build such a thing.

A real JSP programmer can implement also recursive routines in COBOL using inversion. Can you do that? Can you give an example of that? Suppose a very little program with example input:

I
A
A
M
C
C
R
R
O
O
X
X
M
I

That gives in characters a tree:

Code:
      I
      *
 ***********
 *         *
 A         M
           *
      ****************
      *    *    *    *
      C    R    O    X

In the time I was a JSP coach, this was one of the problems during the course. Of course, the input can be of any kind. The output must be a balanced tree. A component of the tree is described by two records. A component can be a leave or a (sub-)tree. The first record with the component-name opens it, the second record ends it.

I would like to see your solution for that using your way to code it.

Regards,

Crox
 
Hi Crox

I won't be a apostle of coroutines nor JSP nor any other religion. My only purpose is to show further possibilities of COBOL.

With regard to your sensible questions about maintenance and alike, as soon as possible I'll show a more structured approach, where the role of virtual files (pipes) is accentuated.

For your interesting exercise I have no solution based on coroutines, but this means nothing since you know that every solution adapts well to a specific class of problems and not to others.

Regards
Alessandro
 
hi,
I dont understand.
Please, do you have one sample of complete source code cobol?

send me marcos_as@terra.com.br

thanks

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top