open Tracer let pgm = Sys.argv.(0) let addr = Unix.ADDR_INET (Join.Site.get_local_addr(),12345) let () = Join.Site.listen addr let nclients,level, n = try begin match Sys.argv with | [| _ ; lvl ; n |] -> 0, int_of_string lvl, int_of_string n | [| _ ; lvl ; n ; nc |] -> int_of_string nc, int_of_string lvl, int_of_string n | _ -> raise Exit end with _ -> 0, 9, 512 let client = if Filename.check_suffix pgm ".opt" then "./client.opt" else "./client" let rec fork_clients n = match n with | 0 -> [] | _ -> match Unix.fork() with | 0 -> begin try Unix.execv client [| client |] with _ -> exit 127 end | pid -> pid::fork_clients (n-1) let pids = fork_clients nclients let scene = create level { x = 0.; y = -1.; z = 4. } 1. and ss = 4 (************************) (* The distributed loop *) (************************) let create_loop scene ss n = (* Line collector - collect n lines , - before returning the image (array of lines) to whoever called wait *) let create_collector () = let img = Array.make n "" in def count(0) & wait() = reply img to wait or count(n) & collect(y,v) = img.(y) <- v ; count(n-1) & reply to collect in spawn count(n) ; collect,wait in let collect,wait = create_collector () in (* Actual loop, nothing fancy *) def loop(y,go) & agent(worker) = (* issue next line, if appropriate *) begin if go && y+1 < n then loop(y+1,go) end & (* call worker *) begin let v = try Some (worker(y)) with _ -> None in match v with | Some v -> (* worker still here *) collect(y,v) ; agent(worker) (* and is ready for a new line *) | None -> (* worker failed, re-issue line *) loop(y,false) end in (* start at line 0 *) spawn loop(0,true) ; (* registering client will return a worker when supplied with the scene *) def register(make_worker) = agent(make_worker (scene,ss,n)) in register, wait let register, wait = create_loop scene ss n let ns = Join.Ns.here let () = Join.Ns.register ns "register" (register : Tracer.agent Join.chan) (* Wait for all lines and print them *) let () = let img = wait () in Printf.printf "P5\n%d %d\n255\n" n n; for y = n - 1 downto 0 do output_string stdout img.(y) done