Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
123
Task/Dining-philosophers/Erlang/dining-philosophers-1.erl
Normal file
123
Task/Dining-philosophers/Erlang/dining-philosophers-1.erl
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
%%%
|
||||
%%% to compile and run:
|
||||
%%% $ erl
|
||||
%%% > c(rosetta).
|
||||
%%% {ok,rosetta}
|
||||
%%% > rosetta:dining().
|
||||
%%%
|
||||
%%% contributor: bksteele
|
||||
%%%
|
||||
-module(rosetta).
|
||||
-export([dining/0]).
|
||||
|
||||
sleep(T) ->
|
||||
receive
|
||||
after T ->
|
||||
true
|
||||
end.
|
||||
|
||||
doForks(ForkList) ->
|
||||
receive
|
||||
{grabforks, {Left, Right}} ->
|
||||
doForks(ForkList -- [Left, Right]);
|
||||
{releaseforks, {Left, Right}} ->
|
||||
doForks([Left, Right| ForkList]);
|
||||
{available, {Left, Right}, Sender} ->
|
||||
Sender ! {areAvailable,
|
||||
lists:member(Left, ForkList)
|
||||
andalso lists:member(Right, ForkList)},
|
||||
doForks(ForkList);
|
||||
{die} -> io:format("Forks put away.~n")
|
||||
end.
|
||||
|
||||
areAvailable(Forks) ->
|
||||
forks ! {available, Forks, self()},
|
||||
receive
|
||||
{areAvailable, false} -> false;
|
||||
{areAvailable, true} -> true
|
||||
end.
|
||||
|
||||
|
||||
processWaitList([]) -> false;
|
||||
processWaitList([H|T]) ->
|
||||
{Client, Forks} = H,
|
||||
case areAvailable(Forks) of
|
||||
true -> Client ! {served},
|
||||
true;
|
||||
false -> processWaitList(T)
|
||||
end.
|
||||
|
||||
doWaiter([], 0, 0, false) ->
|
||||
forks ! {die},
|
||||
io:format("Waiter is leaving.~n"),
|
||||
diningRoom ! {allgone};
|
||||
doWaiter(WaitList, ClientCount, EatingCount, Busy) ->
|
||||
receive
|
||||
{waiting, Client} ->
|
||||
WaitList1 = [Client|WaitList],
|
||||
% add to waiting list
|
||||
case (not Busy) and (EatingCount<2) of
|
||||
true ->
|
||||
Busy1 = processWaitList(WaitList1);
|
||||
false -> Busy1 = Busy
|
||||
end,
|
||||
doWaiter(WaitList1, ClientCount, EatingCount, Busy1);
|
||||
|
||||
{eating, Client} ->
|
||||
doWaiter(WaitList -- [Client], ClientCount, EatingCount+1, false);
|
||||
|
||||
{finished} ->
|
||||
doWaiter(WaitList, ClientCount, EatingCount-1,
|
||||
processWaitList(WaitList));
|
||||
{leaving} ->
|
||||
doWaiter(WaitList, ClientCount-1, EatingCount, Busy)
|
||||
end.
|
||||
|
||||
|
||||
philosopher(Name, _Forks, 0) ->
|
||||
io:format("~s is leaving.~n", [Name]),
|
||||
waiter ! {leaving};
|
||||
philosopher(Name, Forks, Cycle) ->
|
||||
io:format("~s is thinking.~n", [Name]),
|
||||
sleep(rand:uniform(1000)),
|
||||
io:format("~s is hungry.~n", [Name]),
|
||||
% sit at table
|
||||
waiter ! {waiting, {self(), Forks}},
|
||||
|
||||
receive
|
||||
{served} -> forks ! {grabforks, Forks},
|
||||
% grab forks
|
||||
waiter ! {eating, {self(), Forks}},
|
||||
% start eating
|
||||
io:format("~s is eating.~n", [Name])
|
||||
end,
|
||||
|
||||
sleep(rand:uniform(1000)),
|
||||
% put forks down
|
||||
forks ! {releaseforks, Forks},
|
||||
waiter ! {finished},
|
||||
|
||||
philosopher(Name, Forks, Cycle-1).
|
||||
|
||||
|
||||
dining() -> AllForks = [1, 2, 3, 4, 5],
|
||||
Clients = 5,
|
||||
register(diningRoom, self()),
|
||||
|
||||
register(forks,
|
||||
spawn(fun() -> doForks(AllForks) end)),
|
||||
register(waiter,
|
||||
spawn(fun() -> doWaiter([], Clients, 0, false) end)),
|
||||
% run for 7 cycles
|
||||
Life_span = 7,
|
||||
spawn(fun() -> philosopher('Aristotle', {5, 1}, Life_span) end),
|
||||
spawn(fun() -> philosopher('Kant', {1, 2}, Life_span) end),
|
||||
spawn(fun() -> philosopher('Spinoza', {2, 3}, Life_span) end),
|
||||
spawn(fun() -> philosopher('Marx', {3, 4}, Life_span) end),
|
||||
spawn(fun() -> philosopher('Russell', {4, 5}, Life_span) end),
|
||||
|
||||
receive
|
||||
{allgone} -> io:format("Dining room closed.~n")
|
||||
|
||||
end,
|
||||
unregister(diningRoom).
|
||||
197
Task/Dining-philosophers/Erlang/dining-philosophers-2.erl
Normal file
197
Task/Dining-philosophers/Erlang/dining-philosophers-2.erl
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
%%% This version uses free-running 'phil' agents (actors) and
|
||||
%%% state machines representing the forks.
|
||||
%%%
|
||||
%%% Usage to compile and run:
|
||||
%%% $ erl
|
||||
%%% > c(dining).
|
||||
%%% {ok,dining}
|
||||
%%% > dining:start().
|
||||
%%%
|
||||
|
||||
-module( dining).
|
||||
-export(
|
||||
[ start/0
|
||||
]).
|
||||
-vsn( 1).
|
||||
-date( '6/2020').
|
||||
-author( bksteele).
|
||||
-email( 'drbenkman@gmail.com').
|
||||
|
||||
%% fork messages: grab | drop | quit
|
||||
%% a quit message is accepted only when State = available
|
||||
%% @param Id numeric identification of object
|
||||
%% @param State: available | in_use
|
||||
|
||||
fork( Id, available ) ->
|
||||
receive
|
||||
{ From, Who, grab} ->
|
||||
From ! { self(), Who, Id}
|
||||
, fork( Id, in_use)
|
||||
;
|
||||
{ From, quit} ->
|
||||
From ! { quit}
|
||||
, ok
|
||||
end
|
||||
;
|
||||
fork( Id, in_use ) ->
|
||||
receive
|
||||
{ From, Who, drop} ->
|
||||
From ! { self(), Who, Id}
|
||||
, fork( Id, available)
|
||||
end
|
||||
.
|
||||
|
||||
%% sleep/1 : Integer -> ok
|
||||
%% sleep pauses a process for T milliseconds.
|
||||
%% @param T milliseconds for the time period
|
||||
|
||||
sleep(T) ->
|
||||
receive
|
||||
after T -> true
|
||||
end
|
||||
.
|
||||
|
||||
%% grab/2 : Pid String -> ()
|
||||
%% Fork is the shared resource (a process object).
|
||||
%% Who is the name of the acting process.
|
||||
%% grab encapsulates message transmission.
|
||||
%% @param Fork pid to which to send messages
|
||||
%% @param Who name of the sender
|
||||
|
||||
grab( Fork, Who) ->
|
||||
Fork ! { self(), Who, grab}
|
||||
, receive
|
||||
{ Fork, Who, _Id} -> ok
|
||||
end
|
||||
.
|
||||
|
||||
%% drop/2 : Pid String -> ()
|
||||
%% Fork is the shared resource (a process object).
|
||||
%% Who is the name of the acting process.
|
||||
%% drop encapsulates message transmission.
|
||||
%%
|
||||
%% @param Fork pid to which to send messages
|
||||
%% @param Who name of the sender
|
||||
|
||||
drop( Fork, Who) ->
|
||||
Fork ! { self(), Who, drop}
|
||||
, receive
|
||||
{ Fork, Who, _Id} -> ok
|
||||
end
|
||||
.
|
||||
|
||||
|
||||
%% phil/3 : String List{Id,Pid} Integer -> ok
|
||||
%% phil/3 philosopher process uses a fork process.
|
||||
%% phil uses two fork objects for n eating cycles.
|
||||
%% A phil needs the pids of resource to communicate,
|
||||
%% and the names of the fork resources it uses.
|
||||
%% @param Name the string name of the philosopher
|
||||
%% @param List{Id, Pid} 2 pairs of Id and Fork
|
||||
%% @param Cycle the number of cycles to run
|
||||
|
||||
phil( Name, [{LId, Left}, {RId, Right}], Cycle)
|
||||
when LId > RId ->
|
||||
% swap so that process picks numerically lower first.
|
||||
% the swap introduces asymmetry to prevent deadlock.
|
||||
phil( Name, {RId, Right}, {LId, Left}, Cycle)
|
||||
;
|
||||
phil( Name, [{LId, Left}, {RId, Right}], Cycle) ->
|
||||
phil( Name, {LId, Left}, {RId, Right}, Cycle).
|
||||
|
||||
|
||||
%% phil/4 : String {LId,LeftF} {RId,RightF} Integer -> ok
|
||||
%% phil/4 philosopher process uses a fork process.
|
||||
%% phil uses two fork objects for n eating cycles.
|
||||
%% A phil needs pids of resource to communicate
|
||||
%% and the names of the fork resources it uses.
|
||||
%% @param Name the string name of the philosopher
|
||||
%% @param {LeftId, Fork} pair of Id and Fork pid
|
||||
%% @param {RightId, Fork} pair of Id and Fork pid
|
||||
%% @param Cycle the number of cycles to run
|
||||
|
||||
phil( Name, _LFork, _RFork, 0) ->
|
||||
io:format( "~s is done.~n", [Name])
|
||||
;
|
||||
phil( Name, {LId, Left}, {RId, Right}, Cycle) ->
|
||||
|
||||
io:format( "~s is thinking.~n", [Name])
|
||||
, sleep( rand:uniform( 1000))
|
||||
, io:format( "~s is hungry.~n", [Name])
|
||||
|
||||
, grab( Left, Name)
|
||||
, grab( Right, Name)
|
||||
|
||||
, io:format( "~s is eating.~n", [Name])
|
||||
, sleep( rand:uniform( 1000))
|
||||
|
||||
, drop( Left, Name)
|
||||
, drop( Right, Name)
|
||||
|
||||
, phil( Name, [{LId, Left}, {RId, Right}]
|
||||
, Cycle - 1)
|
||||
.
|
||||
|
||||
%% make_forks/1 : N -> List{Id, Fork}
|
||||
|
||||
make_forks( N) when N > 0 -> make_forks( N, []).
|
||||
|
||||
%% make_forks/2 : N List{Id, Fork}
|
||||
|
||||
make_forks( 0, Forks ) -> lists:reverse( Forks)
|
||||
;
|
||||
make_forks( N, Forks) ->
|
||||
% create and run the fork processes
|
||||
Pair = { N, spawn(
|
||||
fun() -> fork( N, available) end) }
|
||||
, make_forks( N-1
|
||||
, lists:append( Forks, [Pair] ))
|
||||
.
|
||||
|
||||
%% make_phils/2 : Names, ForkList -> List{String}
|
||||
|
||||
make_phils( Names, Forks)
|
||||
when length( Names) > 0 ->
|
||||
make_phils( Names, Forks, [])
|
||||
.
|
||||
|
||||
%% make_phils/3 : Names Forks PL -> List{Fun}
|
||||
%% make_phil/3 hard-codes the eat cycle count to 7
|
||||
|
||||
make_phils( [], _Forks, PhilList) -> PhilList
|
||||
;
|
||||
make_phils( [Hn|Tn], [Lf, Rf |FList], PhilList) ->
|
||||
% create a phil process function but do not run yet
|
||||
Phil = fun() -> phil( Hn, [Lf, Rf], 7) end
|
||||
, make_phils( Tn, rot( [Lf, Rf |FList], 1)
|
||||
, lists:append( PhilList, [Phil]))
|
||||
.
|
||||
|
||||
%% rot/2 : List Num -> List
|
||||
%% rotate or roll a list by N slots, and return new list
|
||||
|
||||
rot( List, 0 ) -> List
|
||||
;
|
||||
rot( [H], 1 ) -> [H]
|
||||
;
|
||||
rot( [H|List], N ) ->
|
||||
rot( lists:append( List, [H]), N - 1)
|
||||
.
|
||||
|
||||
%% start free-running philosopher agents competing for Forks
|
||||
%% start is fixed with N = 5 philosophers and 5 forks.
|
||||
|
||||
start() ->
|
||||
% create Fork list
|
||||
N = 5
|
||||
, Forks = make_forks( N)
|
||||
|
||||
, Names = [ "Aristotle", "Kant"
|
||||
, "Spinoza", "Marx", "Russell"]
|
||||
|
||||
, Phils = make_phils( Names, Forks)
|
||||
|
||||
% run the philosophers now
|
||||
, [spawn( P) || P <- Phils]
|
||||
, ok
|
||||
.
|
||||
Loading…
Add table
Add a link
Reference in a new issue