File: phil.ml

package info (click to toggle)
cothreads 0.10-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 500 kB
  • sloc: ml: 1,963; makefile: 216
file content (57 lines) | stat: -rw-r--r-- 1,529 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
(* Classical philosopher dinning problem written in STM. Launch it with [./phil
   n], where n is the number of philosophers and chopsticks.
*)
module Thread=Cothread (* Or use Thread directly *)
open Stm

(* Number of philosophers and chopsticks, the degree *)
let n = 
  try int_of_string Sys.argv.(1) 
  with Invalid_argument _ -> 
    prerr_endline "Launch the program with a single int, e.g. ./phil 5";
    exit 1

let chopstick = Array.init n (fun _ -> tvar true)

let left x = x and right x = (x + 1) mod n

let check b = if b then return () else retry

(* Actions: think, eat, takeup, putdown*)
let think x = 
  Printf.printf "Phil %d begins his THINKING ...\n" x; flush stdout;
  Thread.delay (Random.float 0.1)

let eat x = 
  Printf.printf "Phil %d begins to EAT -----> \n" x;
  Thread.delay (Random.float 0.02);
  Printf.printf "Phil %d now finish EAT <----- \n" x; flush stdout

let chop_act x s l r =
  Printf.printf "Phil %d %s chopstick %d and %d\n" x s l r

let takeup id =
  read_tvar chopstick.(id) >>= check >> write_tvar chopstick.(id) false

let putdown id =
  write_tvar chopstick.(id) true 

(* Philosopher thread function *)
let phil x =
  let l,r = (left x, right x) in
  let rec run () = 
    think x;
    atom (takeup l >> takeup r);
    chop_act x "take up" l r;
    eat x;
    atom (putdown l >> putdown r);
    chop_act x "put down" l r;
    run () in
  Random.self_init ();
  run ()

let main () =
  let phils = Array.init n (Thread.create phil) in
  Array.iter Thread.join phils

let _ = main ()