(* this program simulates a bank and its clients *) open Thread open Event open Printf (* utility functions *) let post c x = sync (send c x) let accept c = sync (receive c) (* printf stub function *) let l = Mutex.create () let printf fmt = Mutex.lock l; Printf.kprintf (fun s -> printf "%s" s; flush stdout; Mutex.unlock l) fmt (* bank function for the bank thread *) let rec bank safe c = let id, amt, c' = accept c in let () = flush stdout in let () = printf "%i begin transaction (amt:%.2f)\n" id amt in try let old_balance = List.assoc id safe in let new_balance = old_balance +. amt in if new_balance > 0.0 then ( (* valid transaction *) let new_safe = List.map (fun (t_id, t_amt) -> if t_id = id then (t_id, new_balance) else (t_id, t_amt) ) safe in printf "%i transaction complete (balance: $%.2f)\n" id new_balance; post c' (List.assoc id new_safe); bank new_safe c ) else ( (* invalid transaction *) printf "%i transaction DENIED (balance: $%.2f)\n" id old_balance; post c' (List.assoc id safe); bank safe c ) with Not_found -> if amt >= 0.0 then ( (* valid account creation *) printf "%i account is created (balance: $%.2f)\n" id amt; post c' amt; bank ((id, amt)::safe) c ) else ( (* invalid account creation *) printf "%i account DOESN'T exist, transaction DENIED...\n" id; post c' amt; bank safe c ) (* client function for client threads *) let rec client id requests bank_c my_c = match requests with | [] -> () (* done *) | h::t -> printf "%i requesting transaction %.2f\n" id h; post bank_c (id, h, my_c); ignore(accept my_c); delay 0.5; (* to slow things down *) client id t bank_c my_c (* remember, only one bank thread *) let bank_c = new_channel () let () = let () = print_endline "starting simulation..." in let bt = create (bank []) bank_c in let ct1 = create (client 1001 [0.0; 2.0; -3.0] bank_c) (new_channel ()) in let ct2 = create (client 1002 [0.0; 3.0; 1.0; -1.0; 2.0] bank_c) (new_channel ()) in let ct3 = create (client 1003 [-1.0; 3.0; 8.0] bank_c) (new_channel ()) in let ct4 = create (client 1004 [1.0; 1.0] bank_c) (new_channel ()) in (* join the client threads; this makes the main thread to wait until all cliens are done *) Thread.join ct1; Thread.join ct2; Thread.join ct3; Thread.join ct4; printf "ending simulation...\n"; ()