[Shootout-list] Haskell killer prodcons implementation - fair?

Raymond Racine rracine@adelphia.net
Sun, 03 Oct 2004 01:49:47 -0400


--=-TaOqzEFh5ApALIqxPPPq
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

On Sat, 2004-10-02 at 19:46, Brent Fulgham wrote:
> It seems fair.  The MVar construct provides the concurrency 
> synchronization
> we need to verify that one "thread" is not reading the value at the 
> same time
> the other is writing to the buffer.

SML has a (unoffical) standard for concurrency as well, CML.
See http://cml.cs.uchicago.edu/

It should work for both SML/NJ and MLton.  I only tested MLton however.

The MLton port of CML is fairly new and may or may not be available
depending on what version of MLton you have.  The new prodcon.sml
version is smaller, easier to understand and I believe faster. (Can't
confirm because the current prodcon.sml will not compile.  I believe the
thread sig has changed in the lastest CVS head for MLton.)

BTW I think the latest Haskell version is hand waving the
consumer/producer count/increment requirement a tad.  Though I agree the
mVar approach itself is fair.

Ray





--=-TaOqzEFh5ApALIqxPPPq
Content-Disposition: attachment; filename=prodcon.mlb
Content-Type: text/plain; name=prodcon.mlb; charset=UTF-8
Content-Transfer-Encoding: 7bit

$(MLTON_ROOT)/basis/basis.mlb
$(MLTON_ROOT)/cml/cml.mlb

local
    prodcon.sml
in
    structure Main
end

--=-TaOqzEFh5ApALIqxPPPq
Content-Disposition: attachment; filename=prodcon.sml
Content-Type: application/x-smil; name=prodcon.sml
Content-Transfer-Encoding: 7bit

(* See conccurnt CML library for SML 
   http://cml.cs.uchicago.edu/ *)

structure Main =
struct

  val consumed = ref 0
  val produced = ref 0

  fun cinc() = consumed := !consumed + 1
  fun pinc() = produced := !produced + 1
	       
  fun consumer (chan,n) = CML.spawn (fn () => while !consumed < n do (CML.recv chan; cinc()))
			
  fun producer (chan,n) = CML.spawn (fn () => while !produced < n do (CML.send (chan,!produced); pinc()))
	  
  fun doit n = let fun run () = let val chan = CML.channel()
				    val ctid = consumer (chan,n)
				    val ptid = producer (chan,n)
				in
				    CML.sync (CML.joinEvt ctid);
				    RunCML.shutdown OS.Process.success
				end
	       in
		   RunCML.doit (run, NONE);
		   print (Int.toString (!consumed) ^ " " ^ Int.toString (!produced))
	       end
		   
end
  
val _ = let val arg0 = List.hd (CommandLine.arguments())
	in
	    Main.doit (Option.getOpt (Int.fromString arg0,0))
	end 
	    

--=-TaOqzEFh5ApALIqxPPPq--