\begin{xple}
(*
   Using rendevous:

   Bounded buffer implementation
*)
   
(* Create two communication channels (aka rendevous) *)
\k{let} append = rendevous.new(0)
\k{let} take   = rendevous.new(\k{tuple} \k{let} \k{var} x = 0 \k{end})
\k{let} infix// = real.div

(* This function implements an integer buffer with give size *)

\k{let} buffer(size :Int) = \k{begin}
  \k{let} \k{var} b = arrayOp.new(size 0)         (* The 'real' buffer *)
  \k{let} \k{var} inptr  = 0
  \k{let} \k{var} outptr = 0
  \k{let} \k{var} n = 0
 

  \k{let} printb() =                          (* Only to show what happens *)
    \k{begin}
      \k{for} i=0 \k{upto} size-1 \k{do}
        print.int(b[i])
        print.string(" | ")
      \k{end}
      print.string("inptr|outptr = "<> fmt.int(inptr)<>"|"<>fmt.int(outptr))
      print.ln()
      print.string("n = " <> fmt.int(n) <> "\n")
    \k{end}

  thread.fork(\k{fun}(self :thread.T(\k{Ok}))
    \k{loop}
      thread.atomic(\k{fun}() \k{begin}
        printb() 
      \k{end})
      thread.sleep(0.5) 
    \k{end})

  (* Append value to buffer and uptdate buffer write pointer *)
  (* This function will be called during rendevous *)
  \k{let} appendFun(x :Int) =                 
    \k{begin}
      b[inptr] := x
      n := n + 1
      inptr := {inptr + 1} % size
    \k{end}

  (* Take value from buffer and uptdate buffer read pointer *)
  (* This function will be called during rendevous *)
  \k{let} takeFun(x :\k{Tuple} \k{var} x :Int \k{end}) =
    \k{begin}
      x.x := b[outptr]
      n := n - 1
      outptr:= {outptr + 1} % size
    \k{end}
      
  (* Make rendevous entrys *)
  \k{let} append = rendevous.makeEntry(append  appendFun  \k{fun}() n < size)
  \k{let} take = rendevous.makeEntry(take  takeFun  \k{fun}() n > 0 )


  (* Do the work ... *)
  \k{loop}
    rendevous.select(array append take \k{end} )
  \k{end}
\k{end}   

\k{let} producer(s, n :Int) = 
  \k{begin}
    \k{for} i=s \k{upto} n \k{do}
      rendevous.put(append i)
      thread.sleep(real.val(rand() % 10) // 40.0)
    \k{end}
  \k{end}

\k{let} consumer() = 
  \k{begin}
    \k{let} val = \k{tuple} \k{let} \k{var} x = 0 \k{end}
    \k{loop}
      rendevous.put(take val)
      thread.sleep(real.val(rand() % 10) // 40.0)
    \k{end}
  \k{end}

\k{let} t1 = thread.fork(\k{fun}(self :thread.T(\k{Ok})) buffer(10))
\k{let} t2 = thread.fork(\k{fun}(self :thread.T(\k{Ok})) producer(0 1000))
\k{let} t3 = thread.fork(\k{fun}(self :thread.T(\k{Ok})) consumer())
\k{let} t4 = thread.fork(\k{fun}(self :thread.T(\k{Ok})) producer(100000 101000))
\k{let} t5 = thread.fork(\k{fun}(self :thread.T(\k{Ok})) consumer())
;

\end{xple}

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "qq"
%%% End: 
