A-M baby
This commit is contained in:
parent
764da6cbbb
commit
db842d013d
19005 changed files with 197040 additions and 7 deletions
21
Task/Dining-philosophers/JoCaml/dining-philosophers-1.jocaml
Normal file
21
Task/Dining-philosophers/JoCaml/dining-philosophers-1.jocaml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
let random_wait n = Unix.sleep (Random.int n);;
|
||||
let print s m = Printf.printf "philosopher %s is %s\n" s m; flush(stdout);;
|
||||
let will_eat s = print s "eating"; random_wait 10;;
|
||||
let will_think s = print s "thinking"; random_wait 20; print s "hungry";;
|
||||
|
||||
(* a,b,c,d,e are thinking philosophers; ah,bh,ch,dh,eh are the same philosophers when hungry;
|
||||
fab is the fork located between philosophers a and b; similarly for fbc, fcd, ... *)
|
||||
|
||||
def ah() & fab() & fea() = will_eat "Aristotle"; a() & fab() & fea()
|
||||
or bh() & fab() & fbc() = will_eat "Kant"; b() & fab() & fbc()
|
||||
or ch() & fbc() & fcd() = will_eat "Spinoza"; c() & fbc() & fcd()
|
||||
or dh() & fcd() & fde() = will_eat "Marx"; d() & fcd() & fde()
|
||||
or eh() & fde() & fea() = will_eat "Russell"; e() & fde() & fea()
|
||||
|
||||
and a() = will_think "Aristotle"; ah()
|
||||
and b() = will_think "Kant"; bh()
|
||||
and c() = will_think "Spinoza"; ch()
|
||||
and d() = will_think "Marx"; dh()
|
||||
and e() = will_think "Russell"; eh()
|
||||
;;
|
||||
spawn fab() & fbc() & fcd() & fde() & fea() & a() & b() & c() & d() & e();;
|
||||
47
Task/Dining-philosophers/JoCaml/dining-philosophers-2.jocaml
Normal file
47
Task/Dining-philosophers/JoCaml/dining-philosophers-2.jocaml
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
let print s t m = Printf.printf "t=%d: philosopher %s is %s\n" t s m; flush(stdout);;
|
||||
let random_wait n = Unix.sleep (Random.int n);;
|
||||
|
||||
(* auxiliary function to keep track of time ticks, using integer seconds *)
|
||||
def ts () & counter(n) = counter(n) & reply n to ts
|
||||
or update_counter() & counter(n) = counter(n+1) & reply to update_counter
|
||||
and counter_sentinel() = Unix.sleep 1; update_counter(); counter_sentinel()
|
||||
;;
|
||||
spawn counter(0) & counter_sentinel();;
|
||||
|
||||
def stats(n, waited, maxwaited) & report_wait_time(m) =
|
||||
let (n', waited', maxwaited') = (n+1, waited+m, max maxwaited m) in
|
||||
Printf.printf "waiting average %f, max waited %d\n"
|
||||
(float_of_int waited' /. float_of_int n')
|
||||
maxwaited';
|
||||
flush(stdout);
|
||||
stats(n',waited',maxwaited') & reply () to report_wait_time
|
||||
;;
|
||||
|
||||
spawn stats(0,0,0);;
|
||||
|
||||
let eat s t = print s t "eating"; random_wait 10;;
|
||||
let think s = print s (ts()) "thinking"; random_wait 20;;
|
||||
|
||||
(* "p" will be a philosopher channel, to be defined later
|
||||
the messages ah, bh, ... do not need to be injected now. *)
|
||||
|
||||
let will_eat s t = let t' = ts() in report_wait_time(t'-t); eat s t';;
|
||||
|
||||
def ah(t,p) & fab() & fea() = will_eat "Aristotle" t; p() & fab() & fea()
|
||||
or bh(t,p) & fab() & fbc() = will_eat "Kant" t; p() & fab() & fbc()
|
||||
or ch(t,p) & fbc() & fcd() = will_eat "Spinoza" t; p() & fbc() & fcd()
|
||||
or dh(t,p) & fcd() & fde() = will_eat "Marx" t; p() & fcd() & fde()
|
||||
or eh(t,p) & fde() & fea() = will_eat "Russell" t; p() & fde() & fea()
|
||||
;;
|
||||
|
||||
spawn fab() & fbc() & fcd() & fde() & fea();;
|
||||
|
||||
(* define the thinking -> hungry transitions using local philosophers, and inject the philosophers *)
|
||||
List.map
|
||||
(fun (h,s) -> def p() = think s; let t = ts() in print s t "hungry"; h(t,p) in spawn p())
|
||||
[(ah,"Aristotle"); (bh,"Kant"); (ch,"Spinoza"); (dh,"Marx"); (eh,"Russell")]
|
||||
;;
|
||||
(* this replaces repetitive code such as that shown in the previous solution *)
|
||||
|
||||
(* now we need to wait and do nothing; nobody will be able to inject godot() *)
|
||||
def wait_forever() & godot() = reply () to wait_forever in wait_forever();;
|
||||
77
Task/Dining-philosophers/JoCaml/dining-philosophers-3.jocaml
Normal file
77
Task/Dining-philosophers/JoCaml/dining-philosophers-3.jocaml
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
#!/usr/bin/jocamlrun jocaml
|
||||
|
||||
(* eating and thinking between 0 and this-1 *)
|
||||
let eating_max_interval = 10;;
|
||||
let thinking_max_interval = 10;;
|
||||
let number_of_philosophers = 5;;
|
||||
let random_wait n = Unix.sleep (Random.int n);;
|
||||
|
||||
(* counter for unique timestamp, not related to time in seconds *)
|
||||
def get_current_time () & unique_ts_counter(n) = unique_ts_counter(n+1) & reply n to get_current_time;;
|
||||
spawn unique_ts_counter(0);;
|
||||
|
||||
(* functions that wait and print diagnostics *)
|
||||
let name i = List.nth ["Aristotle"; "Kant"; "Spinoza"; "Marx"; "Russell"] i;;
|
||||
let message i m = Printf.printf "philosopher %s is %s\n" (name i) m; flush(stdout);;
|
||||
let eat i = message i "eating"; random_wait eating_max_interval;;
|
||||
let think i = message i "thinking"; random_wait thinking_max_interval;;
|
||||
|
||||
type philosopher_state_t = Eating | Hungry of int | Thinking;;
|
||||
|
||||
(* initial states *)
|
||||
let states = Array.make number_of_philosophers Thinking;;
|
||||
(* one philosopher's processes *)
|
||||
let make_philosopher i got_hungry done_eating =
|
||||
def hungry() & forks() = eat i ; done_eating(i) & thinking()
|
||||
and thinking() = think i; got_hungry(i) & hungry()
|
||||
in spawn thinking(); forks
|
||||
;;
|
||||
|
||||
(* deciding who will eat first *)
|
||||
let next_phil i = (i+1) mod number_of_philosophers;;
|
||||
let prev_phil i = (number_of_philosophers+i-1) mod number_of_philosophers;;
|
||||
let is_hungry p = match p with
|
||||
| Hungry h -> true
|
||||
| _ -> false;;
|
||||
let not_eating p = match p with
|
||||
| Eating -> false
|
||||
| _ -> true;;
|
||||
let is_more_hungry p q = match q with
|
||||
| Hungry hj -> (
|
||||
match p with
|
||||
| Hungry hi -> hi <= hj
|
||||
| _ -> false
|
||||
)
|
||||
| _ -> true
|
||||
;;
|
||||
|
||||
let may_eat_first i =
|
||||
is_hungry states.(i)
|
||||
&& not_eating states.(next_phil i) && not_eating states.(prev_phil i)
|
||||
&& is_more_hungry states.(i) states.(next_phil i)
|
||||
&& is_more_hungry states.(i) states.(prev_phil i);;
|
||||
|
||||
let decide_eating i =
|
||||
if (may_eat_first i) then (states.(i) <- Eating; true)
|
||||
else false;;
|
||||
|
||||
def waiter(all_forks) & got_hungry(i) =
|
||||
states.(i) <- Hungry (get_current_time());
|
||||
let will_eat = decide_eating i in (
|
||||
waiter(all_forks) & (if will_eat then all_forks.(i)() else 0)
|
||||
)
|
||||
or waiter(all_forks) & done_eating(i) =
|
||||
states.(i) <- Thinking;
|
||||
let next_will_eat = decide_eating (next_phil i) in
|
||||
let prev_will_eat = decide_eating (prev_phil i) in (
|
||||
waiter(all_forks)
|
||||
& (if next_will_eat then all_forks.(next_phil i)() else 0)
|
||||
& (if prev_will_eat then all_forks.(prev_phil i)() else 0)
|
||||
);;
|
||||
|
||||
let all_forks = Array.init number_of_philosophers (fun i -> make_philosopher i got_hungry done_eating)
|
||||
in spawn waiter(all_forks);;
|
||||
|
||||
(* now we need to wait and do nothing; nobody will be able to inject godot() *)
|
||||
|
||||
def wait_forever() & godot() = reply () to wait_forever in wait_forever();;
|
||||
156
Task/Dining-philosophers/Logtalk/dining-philosophers.logtalk
Normal file
156
Task/Dining-philosophers/Logtalk/dining-philosophers.logtalk
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
:- category(chopstick).
|
||||
|
||||
% chopstick actions (picking up and putting down) are synchronized using a notification
|
||||
% such that a chopstick can only be handled by a single philosopher at a time:
|
||||
|
||||
:- public(pick_up/0).
|
||||
pick_up :-
|
||||
threaded_wait(available).
|
||||
|
||||
:- public(put_down/0).
|
||||
put_down :-
|
||||
threaded_notify(available).
|
||||
|
||||
:- end_category.
|
||||
|
||||
|
||||
:- object(cs1,
|
||||
imports(chopstick)).
|
||||
|
||||
:- threaded.
|
||||
:- initialization(threaded_notify(available)).
|
||||
|
||||
:- end_object.
|
||||
|
||||
|
||||
:- object(cs2,
|
||||
imports(chopstick)).
|
||||
|
||||
:- threaded.
|
||||
:- initialization(threaded_notify(available)).
|
||||
|
||||
:- end_object.
|
||||
|
||||
|
||||
:- object(cs3,
|
||||
imports(chopstick)).
|
||||
|
||||
:- threaded.
|
||||
:- initialization(threaded_notify(available)).
|
||||
|
||||
:- end_object.
|
||||
|
||||
|
||||
:- object(cs4,
|
||||
imports(chopstick)).
|
||||
|
||||
:- threaded.
|
||||
:- initialization(threaded_notify(available)).
|
||||
|
||||
:- end_object.
|
||||
|
||||
|
||||
:- object(cs5,
|
||||
imports(chopstick)).
|
||||
|
||||
:- threaded.
|
||||
:- initialization(threaded_notify(available)).
|
||||
|
||||
:- end_object.
|
||||
|
||||
|
||||
:- category(philosopher).
|
||||
|
||||
:- public(left_chopstick/1).
|
||||
:- public(right_chopstick/1).
|
||||
:- public(run/2).
|
||||
|
||||
:- private(message/1).
|
||||
:- synchronized(message/1).
|
||||
|
||||
:- uses(random, [random/3]).
|
||||
|
||||
run(0, _) :-
|
||||
this(Philosopher),
|
||||
message([Philosopher, ' terminated.']).
|
||||
|
||||
run(Count, MaxTime) :-
|
||||
Count > 0,
|
||||
think(MaxTime),
|
||||
eat(MaxTime),
|
||||
Count2 is Count - 1,
|
||||
run(Count2, MaxTime).
|
||||
|
||||
think(MaxTime):-
|
||||
this(Philosopher),
|
||||
random(1, MaxTime, ThinkTime),
|
||||
message(['Philosopher ', Philosopher, ' thinking for ', ThinkTime, ' seconds.']),
|
||||
thread_sleep(ThinkTime).
|
||||
|
||||
eat(MaxTime):-
|
||||
this(Philosopher),
|
||||
random(1, MaxTime, EatTime),
|
||||
::left_chopstick(LeftStick),
|
||||
::right_chopstick(RightStick),
|
||||
LeftStick::pick_up,
|
||||
RightStick::pick_up,
|
||||
message(['Philosopher ', Philosopher, ' eating for ', EatTime, ' seconds with chopsticks ', LeftStick, ' and ', RightStick, '.']),
|
||||
thread_sleep(EatTime),
|
||||
::LeftStick::put_down,
|
||||
::RightStick::put_down.
|
||||
|
||||
% writing a message needs to be synchronized as it's accomplished
|
||||
% using a combination of individual write/1 and nl/0 calls:
|
||||
message([]) :-
|
||||
nl,
|
||||
flush_output.
|
||||
message([Atom| Atoms]) :-
|
||||
write(Atom),
|
||||
message(Atoms).
|
||||
|
||||
:- end_category.
|
||||
|
||||
|
||||
:- object(aristotle,
|
||||
imports(philosopher)).
|
||||
|
||||
left_chopstick(cs1).
|
||||
right_chopstick(cs2).
|
||||
|
||||
:- end_object.
|
||||
|
||||
|
||||
:- object(kant,
|
||||
imports(philosopher)).
|
||||
|
||||
left_chopstick(cs2).
|
||||
right_chopstick(cs3).
|
||||
|
||||
:- end_object.
|
||||
|
||||
|
||||
:- object(spinoza,
|
||||
imports(philosopher)).
|
||||
|
||||
left_chopstick(cs3).
|
||||
right_chopstick(cs4).
|
||||
|
||||
:- end_object.
|
||||
|
||||
|
||||
:- object(marx,
|
||||
imports(philosopher)).
|
||||
|
||||
left_chopstick(cs4).
|
||||
right_chopstick(cs5).
|
||||
|
||||
:- end_object.
|
||||
|
||||
|
||||
:- object(russell,
|
||||
imports(philosopher)).
|
||||
|
||||
left_chopstick(cs1). % change order so that the chopsticks are picked
|
||||
right_chopstick(cs5). % in different order from the other philosophers
|
||||
|
||||
:- end_object.
|
||||
Loading…
Add table
Add a link
Reference in a new issue