-- ==================================================================================
--  WHAT CONCURRENT_HELLO DOES
--
--  This program has two 'writer' processes and one 'output.collector' process. The writers each have a bespoke channel for communication with
--  output.collector. Each writer sends a single digit (int) down it's channel to output.collector. Output.collector receives data from each
--  writer, and prints that digit to the terminal. Everything terminates after each writer has passed 1 message to output.collector. 
--
--  In this architecture (and those that follow in other programms) the writers act as clients to output.collector, which is a server prividing
--  a print-to-the-terminal service.
--
--  This program should be compiled with "kroc -d -di concurrent_hello_1.occ"
--  and then run with ./concurrent_hello_1
-- ==================================================================================


--{{{ this module contains utilities for printint useful types (like strings)
--    (like strings) to a channel (which can be linked to the terminal screen)
#INCLUDE "course.module" 
--}}} 
        

--{{{ PROC outer 
--  outer most procedure, with a parameter list that corresponds to that required to run in unix
PROC outer(CHAN BYTE in?, out!, err!)
  CHAN INT w1.to.oc:                      -- channel for writer.1 to communicate with output.collector
  CHAN INT w2.to.oc:                      -- channel for writer.2 to communicate with output.collector
  VAL INT number.of.writers IS 2:         
  
  --{{{ PROC writer.1
  --  sends a message to output.collector containing the writer's ID
  PROC writer.1 ()
    VAL INT id IS 1 :                     -- constant that stores the ID of this writer.
    SEQ
      w1.to.oc! id
  :
  --}}}
  
  
  --{{{ PROC writer.2
  --  sends a message to output.collector containing the writer's ID
  PROC writer.2 ()
    VAL INT id IS 2 :                     -- constant stores the ID of this writer.
    SEQ
      w2.to.oc! id
  :
  --}}}
  
  
  --{{{ PROC output.collector
  -- process receives data from both the writers (down bespoke channels) and outputs it to the 
  PROC output.collector (CHAN INT in.from.w1, in.from.w2)
    INT data1:
    INT data2:
    INITIAL INT i IS 0:
    --{{{ start receiving and outputting data
    SEQ i = 0 FOR number.of.writers     -- a kind of FOR loop
      ALT                               -- block and wait for one of these channels to have data available
        in.from.w1 ? data1              -- data coming in from writer.1
          SEQ
            out.int(data1, 0, out!)     -- this process call (and the one below it) runs a process in course.module 
            out.string("*n", 0, out!)   -- print a newline
        in.from.w2 ? data2              -- data coming in from writer.2
          SEQ
            out.int(data2, 0, out!)     -- this process call (and the one below it) runs a process in course.module
            out.string("*n", 0, out!)   -- print a newline
    --}}}
  :
  --}}}
  
  
  --{{{ the main body of the program
  SEQ
    out.string("starting the writers...*n", 0, out!)
    PAR             
      output.collector (w1.to.oc, w2.to.oc)     -- start the output collector (this can probably be done in the same PAR block as the writers actually.
--      PAR           -- run two writers together in parallel
      writer.1 ()
      writer.2 ()
    out.string("writers have finished.*n", 0, out!)
  --}}}
:
--}}}



