                         Chapter 15 - Concurrency


                      PREREQUISITES FOR THIS MATERIAL

             In  order to understand this material you should have a
        good grasp of the material in Part I of this tutorial and at
        least  a  cursory  knowledge of the material in  chapter  14
        concerning  the pseudo module SYSTEM and especially the  ADR
        and SIZE functions.

                            WHAT IS CONCURRENCY

             True concurrency is when two processes are taking place
        at exactly the same time with neither affecting the other in
        a  degrading  way.   This is possible in many areas of  your
        life,  such as when the Grandfather clock is running at  the
        same time as the furnace and the television set.   These are
        different  processes all running at the same time.   In  the
        field  of computers,  true concurrency requires at least two
        separate  processors  that are running  completely  separate
        programs or different parts of the same program.

             Usually,   when  computers  are  said  to  be   running
        concurrent  processes,  reference  is being made to  a  time
        sharing  situation in which two or more programs are swapped
        in and out of the computer at a rapid rate,  each getting  a
        small  slice  of time,  a millisecond being  typical.   Each
        process appears to be running constantly but is in fact only
        running a small part of the time,  sort of stuttering.   The
        swapping  in  and out is taking place so fast that,  to  the
        casual user,  it appears that the entire computer is working
        on only his program.

                       WHAT IS MODULA-2 CONCURRENCY?

             The  process in Modula-2,  which is called concurrency,
        is  neither  of the above,  and it should  probably  not  be
        called concurrency.  It is a new way to call and return from
        procedures,  and  although  it is possible to use  this  new
        method of procedure linkage to simulate something that looks
        like concurrent processes,  it is not true concurrency.   It
        is  a part of the language,  and a useful part,  so we  will
        cover it in this chapter.

                            OUR FIRST COROUTINE

             Load  and display the program named COROUT.MOD for  our
        first   look  at  this  new  technique.    Without  lots  of
        explanation,  there are lots of new items IMPORTED and a few
        variables defined, the most interesting being the three that
        are  defined  as  PROCESS type.   These will  be  the  three
        processes we will use in this example.   Next, there are two
        PROCEDURES  which define what the coroutines  will  do.   It


                                 Page 94









                         Chapter 15 - Concurrency


        must  be noted that these PROCEDURES are not allowed to have
        any formal parameters in their headers.   Finally we come to
        the main program which is where we will start to define  how
        to use the coroutines.

             First,  in the main program, we call "NEWPROCESS" which
        loads  a  new process without running it.   We give  it  the
        name  of the procedure where the process can be  found,  and
        give  the  system  a  workspace by  assigning  a  previously
        defined array to it.   This is done by giving the system the
        address and the size of the array.   Finally,  we give it  a
        name  by  which we can call the process.   It must be  noted
        that the workspace must be sufficient for the new process to
        store  all of its variables,  so give the process a generous
        workspace.   If  it is too small,  a runtime error  will  be
        generated.  We then load a second process in preparation for
        running the program by calling NEWPROCESS again.

                         HOW DO WE GET IT STARTED?

             When we began the main program,  we actually loaded and
        started  a process,  the one we are presently executing.  We
        have done this for every program in this tutorial so far but
        paid  no  attention  to it as far as referring to  it  as  a
        process.   We have not given our running process a name yet,
        but we will when we leave it because we have defined another
        PROCESS  type  variable named "main".   To  start  the  next
        process  we  use the TRANSFER function with the name of  the
        process  we wish to terminate and the one we wish to  start.
        This is illustrated in line 43 from which we jump to line 15
        in the process named "Process1".  In Process1 we begin a FOR
        loop where we write a string and a cardinal number then when
        "Index" exceeds 2,  we do another TRANSFER,  this time  from
        Process1  to  Process2.   Thus we jump from line 19  in  one
        procedure  to line 31 in another where we begin an  infinite
        loop.   We print another string in line 32 and once again do
        a TRANSFER from line 33 to somewhere.  The place where we go
        at  this  point is what makes the coroutines different  from
        the standard procedure.

               WHERE DO WE GO WHEN WE RETURN TO A COROUTINE?

             Instead  of  jumping to the beginning of the  procedure
        again,  which would be line 15 in this example, we return to
        the statement following the one we left from.   In this case
        we will return from line 33 to line 20 and complete the loop
        we started earlier.   When Index is increased to 4,  we will
        once again TRANSFER control from line 19 to "Process2",  but
        instead  of jumping to line 31 we will return where we  left
        off there at line 34.   That loop will complete, and we will
        once  again  return  to  line 20.   When  the  FOR  loop  in


                                 Page 95









                         Chapter 15 - Concurrency


        "Process1"  finishes,  we execute lines 24 and 25  then  the
        TRANSFER  in line 26 will return us to the main module  body
        where  we  will arrive at line 44 and complete the last  two
        write  statements  and  do a normal exit  to  the  operating
        system.

             Rather  than  a  technical discussion  of  how  to  use
        coroutines,  this  example was defined step by step.   If it
        was  not  clear,  reread the entire  description  until  you
        understand  it.   There  is really nothing else there is  to
        know  about coroutines other than that knowledge  gained  by
        experience  in  using  them,   which  is  true  of  any  new
        principle  in  computer  programming or any other  facet  of
        life.

                          WHAT WAS ALL THAT ABOUT?

             The thing that is really different about coroutines  is
        the  fact  that they are both (or all three or more)  loaded
        into the computers memory and they stay loaded for the  life
        of the program.   This is not true of normal procedures.  It
        is  transparent  to you,  but procedures are not all  simply
        loaded   into  the  computer  and  left  there,   they   are
        dynamically allocated and started as they are called.   That
        is  why  variables are not saved from one  invocation  of  a
        procedure  to the next.   The variables within a process are
        loaded once, and stay resident for the life of the program.

             In  the  example  program on your  monitor,  all  three
        processss including the main program are loaded and none  is
        really  the main program since any of the programs have  the
        ability to call the others.

             Load  and  display COROUT2.MOD for the  second  example
        with  coroutines.   This program is identical with the  last
        except that two lines are removed from the first process and
        placed in a normal procedure which is called from line 22 to
        illustrate  that some of the code can be placed  outside  of
        the  coroutine  process to make the resident  part  smaller.
        The  implication  here  is that you could have  a  four  way
        coprocess  going  on,  each  one of which had a  very  small
        resident  portion,  and each one of which called  some  huge
        regular procedures.   In fact, there is no reason why two or
        more  of  the  coprocesses could not call  the  same  normal
        procedure.

             Study   this   program   until   you   understand   the
        implications,  then  compile and run it to see that it  does
        exactly the same thing as the last program.




                                 Page 96









                         Chapter 15 - Concurrency


                         HOW ABOUT THREE PROCESSES?

             Load  and display COROUT3.MOD for an example with three
        concurrent  processes.   This  program is identical  to  the
        first program with the addition of another process.  In this
        program,  process 1 calls process 2,  which calls process 3,
        which  once again calls process 1.   Thus the same  loop  is
        traversed  but with one additional stop along the  way.   It
        should  be  evident to you that there is no reason why  this
        could  not  be  extended to any  number  of  processes  each
        calling the next or in any looping scheme you could think up
        provided of course that it had some utilitarian purpose.

                        WHAT IS THE BIG DIFFERENCE?

             Actually,  the  big difference between real  concurrent
        processing and what this is doing is in the division of time
        and  in  who,  or  what,  is doing the  division.   In  real
        concurrent processing,  the computer hardware is controlling
        the operation of the processing and allocating time slots to
        the various processes.   In the pseudo concurrent processing
        we are doing,  it is the processes themselves that are doing
        the  time allocation leading to the possibility that if  one
        of  the  processes  went bad,  it could tie up  all  of  the
        resources  of  the  system and no  other  process  could  do
        anything.   You  could  consider it a challenge to  write  a
        successful  system that really did share time and  resources
        well.

             The important thing to consider about this technique is
        that  it  is  not  a major  breakthrough  in  a  programming
        language, but one additional tool available in Modula-2 that
        is  not  available in the other popular  languages  such  as
        Pascal, C, Fortran, or BASIC.

                  ONE MORE INFINITE EXAMPLE OF CONCURRENCY

             Load  and  display the program named  INFINITE.MOD  for
        another  example  of a program with  concurrency.   In  this
        program,   three   processes  are  created  and  control  is
        transferred  to  the first one after which  they  call  each
        other  in a loop with no provision for ever returning to the
        main program.  The computer will continually loop around the
        three processes checking the printer,  the keyboard, and the
        system  clock  to see if they need servicing.   It  must  be
        pointed out that it would be a simple matter to include  all
        three  checks  in a single loop in the main program  and  do
        away  with all of this extra baggage.   This method had  one
        advantage  over  the simple loop and that is the  fact  that
        each  coprocess  can have its own variables which cannot  be
        affected by the operation of the other processes and yet are


                                 Page 97









                         Chapter 15 - Concurrency


        all memory resident at all times.

             This  program  can  be compiled and  run  but  it  will
        execute  forever  since it has no way to stop it.   You  can
        stop  it because it is writing to the monitor and  therefore
        will be checking the control-break combination.   Simply hit
        control-break  and  the program will be  terminated  by  the
        operating  system.   It  should  be mentioned that  if  this
        technique were used in a real situation,  it would  probably
        not be writing to the monitor continually.

                           IS THIS REALLY USEFUL?

            In a situation where you needed to service interrupts in
        some  prescribed and rapid fashion,  a  technique  involving
        Modula-2  concurrency could prove to be very useful.   There
        are other procedures available in Modula-2 to aid in writing
        a pseudo-concurrent program but they are extrememly advanced
        and would require  an initimate knowledge of your particular
        systems hardware, especially the interrupt system.

             Since  using  these techniques are  extremely  advanced
        programming techniques, they will not be covered here.  They
        are beyond the scope of this tutorial.   It would be to your
        advantage  to  study them and know  that  they  exist,  then
        someday  you  may find that they fill the bill  and  greatly
        simplify some particular programming problem.


























                                 Page 98
