Version française
Home     About     Download     Resources     Contact us    
Browse thread
Smart ways to implement worker threads
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Satoshi Ogasawara <ogasawara@i...>
Subject: Re: [Caml-list] Smart ways to implement worker threads

On 2010/07/16, at 22:02, Goswin von Brederlow wrote:
> Urgs, so what happens if I call "sync (send ...)" twice without the
> other end calling recieve? Lets test:
> 
> let ch = Event.new_channel ()
> ...

That's not good use of synchronous channels. If you want to asynchronous,
try Mbox module in concurrent cell.
https://forge.ocamlcore.org/scm/viewvc.php/trunk/mbox.mli?view=markup&root=ccell

open Printf
open Ccell
open Event

let mbox = Mbox.make ()

let receiver () =
  for i = 0 to 10 do
    printf "received %d\n%!" (sync (Mbox.pop mbox));
    Thread.delay 2.;
  done
    
let _ =
  ignore (Thread.create receiver ());
  for i = 0 to 10 do
    printf "sending %d\n%!" i;
    sync (Mbox.push mbox i);
    Thread.delay 1.;
  done

wednesday:tmp osiire$ ocamlc -thread unix.cma threads.cma -I +site-lib/ccell ccell.cma async.ml && ./a.out
sending 0
received 0
sending 1
received 1
sending 2
sending 3
received 2
sending 4
sending 5
received 3
sending 6
sending 7
received 4
sending 8
sending 9
received 5
sending 10

    
With Mbox module, you can also wait and select long calculation results like this.

open Printf
open Ccell
open Event

let rec forever f x = 
  let v = f x in forever f v

let spawn_loop f x =
  ignore (Thread.create (forever f) x)

let make_worker f =
  let input, output = Mbox.make (), Mbox.make () in
  let work () =
    sync (Mbox.push output (f (sync (Mbox.pop input))));
  in
  spawn_loop work ();
  input, output

let request (input, _) p =
  sync (Mbox.push input p)

let response (_, output) =
  Mbox.pop output

let worker1 = make_worker (printf "action worker1 %d\n%!")
let worker2 = make_worker (printf "action worker2 %d\n%!")
    
let after_long_calc (e1, e2) =
  select [
    wrap e1 (fun _ -> printf "after work1\n%!"; (response worker1, e2));
    wrap e2 (fun _ -> printf "after work2\n%!"; (e1, response worker2));
  ]

let _ =
  spawn_loop after_long_calc (response worker1, response worker2);
  request worker1 1;
  Thread.delay 1.;
  request worker2 2;
  Thread.delay 1.;
  request worker2 3;
  Thread.delay 1.;
  request worker1 4;
  Thread.delay 2.

wednesday:tmp osiire$ ocamlc -thread unix.cma threads.cma -I +site-lib/ccell ccell.cma worker.ml && ./a.out
action worker1 1
after work1
action worker2 2
after work2
action worker2 3
after work2
action worker1 4
after work1


I hope this will be helpful for you.
  
---
  satoshi ogasawara