--
--	sort_pump.occ - recursive sort-pump
--	Copyright (C) 2000 Fred Barnes
--
--	This program is free software; you can redistribute it and/or modify
--	it under the terms of the GNU General Public License as published by
--	the Free Software Foundation; either version 2 of the License, or
--	(at your option) any later version.
--
--	This program is distributed in the hope that it will be useful,
--	but WITHOUT ANY WARRANTY; without even the implied warranty of
--	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--	GNU General Public License for more details.
--
--	You should have received a copy of the GNU General Public License
--	along with this program; if not, write to the Free Software
--	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--

#INCLUDE "dynproc.module"

--{{{  protocols, etc.
PROTOCOL PUMP.PROTO
  CASE
    data; INT
    flush
:
--}}}  

--{{{  PROC sort.pump (VAL DPROCESS me, []CHAN OF ANY x.in, x.out)
PROC sort.pump (VAL DPROCESS me, []CHAN OF ANY x.in, x.out)
  CHAN OF INT in RETYPES x.in[0]:
  CHAN OF BOOL flush RETYPES x.in[1]:
  CHAN OF BOOL terminate RETYPES x.in[2]:
  CHAN OF INT out RETYPES x.out[0]:
  INITIAL BOOL running IS TRUE:
  WHILE running
    PRI ALT
      --{{{  terminate (empty pump)
      BOOL any:
      terminate ? any
        running := FALSE
      --}}}  
      --{{{  flush (empty pump)
      BOOL any:
      flush ? any
        out ! 0
      --}}}  
      --{{{  first bit of data
      INT val:
      in ? val
        INITIAL INT v.count IS 1:
        CHAN OF PUMP.PROTO to.sc, from.sc:
        PAR
          --{{{  start sort.cell
          [1]CHAN OF ANY n.in RETYPES [to.sc]:
          [1]CHAN OF ANY n.out RETYPES [from.sc]:
          INT res:
          INT libhandle:
          SEQ
            ccsp.libhandleof (me, libhandle)
            ccsp.run ("sort.cell", libhandle, n.in, n.out, res)
          --}}}  
          --{{{  process data/events
          SEQ
            to.sc ! data; val
            INITIAL BOOL running.2 IS TRUE:
            WHILE running.2
              PRI ALT
                --{{{  terminate (not allowed in full pipe)
                BOOL any:
                terminate ? any
                  STOP
                --}}}  
                --{{{  flush
                BOOL any:
                flush ? any
                  SEQ
                    to.sc ! flush
                    running.2 := FALSE
                --}}}  
                --{{{  more data
                in ? val
                  SEQ
                    to.sc ! data; val
                    v.count := (v.count + 1)
                --}}}  
            -- pull data out of cells
            out ! v.count
            -- first thing out will be a flush, then all the values
            from.sc ? CASE
              flush
                SKIP
            WHILE (v.count > 0)
              SEQ
                from.sc ? CASE
                  data; val
                    out ! val
                v.count := (v.count - 1)
          --}}}  
      --}}}  
:
--}}}  

--{{{  PROC sort.cell (VAL DPROCESS me, []CHAN OF ANY x.in, x.out)
PROC sort.cell (VAL DPROCESS me, []CHAN OF ANY x.in, x.out)
  CHAN OF PUMP.PROTO in RETYPES x.in[0]:
  CHAN OF PUMP.PROTO out RETYPES x.out[0]:
  in ? CASE
    INT holding:
    data; holding
      SEQ
        CHAN OF PUMP.PROTO c:
        PAR
          --{{{  start another cell
          SEQ
            [1]CHAN OF ANY n.in RETYPES [c]:
            [1]CHAN OF ANY n.out RETYPES [out]:
            INT res:
            INT libhandle:
            SEQ
              ccsp.libhandleof (me, libhandle)
              ccsp.run ("sort.cell", libhandle, n.in, n.out, res)
          --}}}  
          --{{{  sort cell proper
          INITIAL BOOL running IS TRUE:
          WHILE running
            in ? CASE
              INT new:
              data; new
                IF
                  new < holding
                    c ! data; new
                  TRUE
                    SEQ
                      c ! data; holding
                      holding := new
              flush
                SEQ
                  c ! flush
                  running := FALSE
          --}}}  
        out ! data; holding
    flush
      out ! flush
:
--}}}  


