-- Parallel Search Program in occam

DEF n = 100 :  -- must be a constant
CHAN answer[n] -- channels to communicate reply to proc
PAR
  PAR i = [0 FOR n] -- set of search processes
    VAR store[i] :  -- value of each process
    IF
      store[i] = ch
        answer[i]!TRUE
      TRUE
        answer[i]!FALSE
  VAR result, i :  -- collection process
  SEQ
    result := FALSE
    i := 0
    WHILE i<>n   -- cycle around results
      VAR bool :
      SEQ
        answer[i]?bool
        IF
          bool = TRUE   -- stop when one positive reply
            SEQ
              result := TRUE
              chan!i
          TRUE
            i := i+1

-- End of example of Parallel Search   


DEF maxval=20, termin=99 :

PROC originmode(VALUE m,CHAN out[]) =
-- outputs path lengths to internal nodes and the terminator tokens
  SEQ
    SEQ i=[0 to m]
      out[i]!1
    SEQ i_[0 FOR m]
      out[i]!termin   :

PROC internalnode(VALUE n,m,CHAN in[],out[]) =
-- stores minimum input path length on any input, and broadcasts
-- any received value less than the current minimum.  Sends
-- terminator after receipt of terminator from all inputs
  VAR minval, endcount  :
  SEQ
    minval := maxval		-- initially infinity
    endcount := 0
    WHILE TRUE
      VAR val :
      ALT i=[0 FOR n]
        in[i]?val		-- accept any input
          IF
            val = termin
              IF
                endcount = n-1	-- this is the last
                  SEQ i=[0 FOR n]
                    out[i]!termin -- broadcast terminator
                TRUE
                  endcount := endcount+1
            val<minval
              PAR
                minval := val
                SEQ i=[0 FOR m]
                  out[i]!(val+1)	-- braodcast new minimum
            TRUE
              SKIP    :

PROC destinationnode(VALUE n, CHAN in[], numberout) =
-- stores the minimum value input and outputs minimum when all terminators
  VAR mindist  :
  SEQ
    mindist := maxval		-- initially infinity
    WHILE TRUE
      VAR val  :
      ALT i=[0 FOR n]
        in[i]?val		-- accept any input
          IF
            val = termin
              IF
                endcount=n-1	-- last terminator
                  SEQ
                    numberout!mindist
                    STOP
                TRUE
                  endcount := endcount+1
            val < mindist
              mindist := val
            TRUE
              SKIP   :
                    
PROC arc(CHAN in,out) =
  WHILE TRUE
    VAR val  : 
    SEQ
      in?val
      out!val   :

-- Main program
CHAN aout[2], bin[1], bout[2], cin[1], cout[2], din[2], dout[1],
     eout[1], fin[2], screenout  :
PAR
  originnode(2,aout)
  internalnode(1,2,bin,bout)
  internalnode(1,2,cin,cout)
  internalnode(2,1,din,dout)
  internalnode(2,1,ein,eout)
  destinationnode(2,fin,screenout)
  arc(aout[0],cin[0])		-- set up arcs
  arc(aout[1],bin[0])
  arc(bout[0],din[0])
  arc(bout[1],ein[0])
  arc(cout[0],din[1])
  arc(cout[1],ein[1])
  arc(dout[0],fin[0])
  arc(eout[0],fin[1])

-- plus code to print answer
