Pages: [1]   Go Down
Print
Author Topic: bozza filosofi  (Read 1533 times)
0 Members e 1 Utente non registrato stanno visualizzando questa discussione.
Franco Barbanera
Moderator
Forumista Eroico
*****
Offline Offline

Posts: 2.622



WWW
« on: 21-05-2015, 17:53:06 »

-module(diningPhil).
-export([create/1,looptable/1,loopphil/1]).

forks(M,N) ->  if
                    M==1 -> {N,1},;!!..
                    true -> {M-1,M}
                 end.


                   
 

create(N) ->   

   Table = spawn(diningPhil,looptable,[[true| | X<- lists:seq(1,N)],[]]),

   Phils = [spawn(diningPhil,loopphil,[{forks(X,N),X}]) || X <- lists:seq(1,N)]

   true.

num2Pid(N,L) ->  ....   
           

loopphil({{L,R},NumPhil) ->  think(),
                      Table!{request,Num},
                        receive
                            ok -> Table!{request,Num}
                        end,
                        receive
                            ok -> true
                        end,
                             
                    eat(),
                      Table!{release,L},
                      Table!{release,R},
                    loopphil({L,R}).
                     
                     
think() -> erlang:display(pensa),
           erlang:display(self()),
           true.


looptable(ListForksAvailable,PendingReq) ->

        receive
            {request,NumPhil} ->  update(PendingReq,Numphil)
       


                       if available(NumPhil)
                                  -> Phil = num2Pid(NumPhil),
                                          Phil!ok,
                                     receive
                                        {request,Numphil} ->
                                           Phil!ok
                                     end,
                                     looptable(update(ListForksAvailable,NumPhil))
                           true   -> self()!{request,NumPhil},                                   
                                     looptable(ListForksAvailable)
                       end.
« Last Edit: 29-05-2015, 12:04:34 by Franco Barbanera » Logged
xeyes
Matricola
*
Offline Offline

Posts: 4


« Reply #1 on: 30-05-2015, 20:06:45 »

Io l'ho completato così e, in base ai test che ho fatto, sembra funzionare correttamente  pc
Code:
-module(filosofi).
-export([create/1, loopphil/3, looptable/2]).

% ------------------------------------------------------------------------------
% Problema degli N filosofi -- filosofi:create(numero_di_filosofi).
%
% Strategia utilizzata:
% Ciascun filosofo richiede contemporaneamente al tavolo entrambe le forchette
% di cui ha bisogno. Il tavolo accoda le richieste ricevute e, non appena le
% forchette diventano disponibili, invia l'ok al filosofo. Ciò significa che,
% se le forchette sono attualmente disponibili, l'ok viene inviato dal tavolo
% immediatamente alla ricezione della richiesta; se le forchette sono invece già
% in uso, l'ok viene inviato appena esse ritornano entrambe disponibili in
% seguito a release da parte degli attuali utilizzatori.
%
% Il tavolo mantiene due variabili di stato
%  - AvailableForks: Lista di N valori booleani
%  - PendingRequests: Lista di triple {PID, IndiceForkL, IndiceForkR}
%
% Alla ricezione di una request, il tavolo si limita ad accodare la richiesta e
% richiamare la funzione di gestione delle richieste pendenti. Similmente, alla
% ricezione di una release, il tavolo si limita a marcare le forchette come non
% più in uso e poi richiama la funzione di gestione delle richieste pendenti.
% La maggior parte del lavoro viene svolto dalla funzione di gestione delle
% richieste pendenti, che esamina per intero la coda delle richieste (procedendo
% in base all'ordine di arrivo), invia messaggi di ok ai filosofi le cui
% richieste possono essere soddisfatte ed aggiorna lo stato di conseguenza.
% ------------------------------------------------------------------------------

% Funzione ausiliaria che restituisce la coppia degli indici delle forchette
% associate al filosofo M-esimo (N è il numero totale di filosofi)
forks(M, N) ->
if
(M =:= 1) -> {N, 1};
true -> {M - 1, M}
end.

% Crea i processi necessari all'esecuzione di N filosofi
create(N) ->
Table = spawn(filosofi, looptable, [ [ true || _ <- lists:seq(1, N) ], [] ]),
[ spawn(filosofi, loopphil, [ X, forks(X, N), Table ]) || X <- lists:seq(1, N) ],
true.

% Effettua una sleep di durata casuale, stampando un messaggio di stato
wastesometime(NumPhil, Activity) ->
% Inizializzazione del generatore di numeri casuali
{A1, A2, A3} = now(),
random:seed(A1, A2, A3 + NumPhil),

% Estrae un numero compreso tra 500 e 6000
RandomDelayMs = 499 + random:uniform(5501),
io:format("Philosopher ~w will be ~w for ~w milliseconds~n", [ NumPhil, Activity, RandomDelayMs ]),

% Attendo il numero di millisecondi calcolato
timer:sleep(RandomDelayMs).

% Loop di ciascun filosofo
loopphil(NumPhil, Forks, Table) ->
% Penso
wastesometime(NumPhil, thinking),

% Inizio ad avere fame, richiedo entrambe le forchette al tavolo
Table!{request, Forks, self()},

% Attendo che mi vengano concesse
receive
ok -> true
end,

% Mangio
wastesometime(NumPhil, eating),

% Rilascio entrambe le forchette
Table!{release, Forks},

loopphil(NumPhil, Forks, Table).

% Funzione ausiliaria che dati una lista, un indice ed un valore, restituisce
% una lista costruita sostituendo l'elemento indicato con il nuovo valore e
% lasciando invariati tutti gli altri elementi
updatevalueat(List, Index, NewValue) ->
ElementsBefore = lists:sublist(List, Index - 1),
ElementsAfter = lists:nthtail(Index, List),
ElementsBefore ++ [ NewValue ] ++ ElementsAfter.

% Funzione ausiliaria che date le liste delle forchette disponibili e delle
% richieste pendenti cerca di soddisfarle. Le richieste vengono consumate in
% ordine inverso (ovvero dalla fine della lista verso l'inizio).
% La funzione restituisce le liste aggiornate in base alle eventuali richieste
% soddisfatte.
handlependingrequests(AvailableForks, []) ->
% Caso base: non c'è nessuna richiesta da soddisfare, quindi lo stato
% non cambia
{AvailableForks, []};

handlependingrequests(AvailableForks, [Request | OtherRequests]) ->
% Prima di tutto gestiamo le richieste successive a quella considerata
{NewAvailableForks, NewOtherRequests} = handlependingrequests(AvailableForks, OtherRequests),

% Adesso proviamo a vedere se possiamo gestire questa richiesta
{PID, ForkL, ForkR} = Request,
ForkLAvailable = lists:nth(ForkL, NewAvailableForks),
ForkRAvailable = lists:nth(ForkR, NewAvailableForks),
if
(ForkLAvailable and ForkRAvailable) ->
% La richiesta può essere soddisfatta, comunichiamolo al
% filosofo
io:format("Forks ~w and ~w have been granted~n", [ ForkL, ForkR ]),
PID!ok,

% Aggiorniamo la liste delle forchette disponibili
AvailableForksWithoutForkL = updatevalueat(NewAvailableForks, ForkL, false),
AvailableForksWithoutBothForks = updatevalueat(AvailableForksWithoutForkL, ForkR, false),

% La richiesta è stata soddisfatta: non riaccodiamola
{AvailableForksWithoutBothForks, NewOtherRequests};

true ->
% La richiesta non può essere soddisfatta: riaccodiamola
{NewAvailableForks, [Request | NewOtherRequests]}
end.

% Loop di gestione del tavolo
looptable(AvailableForks, PendingRequests) ->
% Gestisci richieste pendenti
{NewAvailableForks, NewPendingRequests} = handlependingrequests(AvailableForks, PendingRequests),

% Ricevi messaggi da filosofi
receive
{request, {ForkL, ForkR}, PID} ->
io:format("Forks ~w and ~w have been requested~n", [ ForkL, ForkR ]),

% Reitera looptable registrando la richiesta ricevuta
looptable(NewAvailableForks, [ {PID, ForkL, ForkR} | NewPendingRequests ]);

{release, {ForkL, ForkR}} ->
io:format("Forks ~w and ~w have been released~n", [ ForkL, ForkR ]),

% Rilascia forchette
AvailableForksWithForkL = updatevalueat(NewAvailableForks, ForkL, true),
AvailableForksWithBothForks = updatevalueat(AvailableForksWithForkL, ForkR, true),

% Reitera looptable tenendo conto delle forchette nuovamente disponibili
looptable(AvailableForksWithBothForks, NewPendingRequests)
end.
Logged
Franco Barbanera
Moderator
Forumista Eroico
*****
Offline Offline

Posts: 2.622



WWW
« Reply #2 on: 09-06-2015, 10:07:47 »


La funzione

updatevalueat(List, Index, NewValue) ->
   ElementsBefore = lists:sublist(List, Index - 1),
   ElementsAfter = lists:nthtail(Index, List),
   ElementsBefore ++ [ NewValue ] ++ ElementsAfter.


va bene, ma come esercizio converrebbe farla utilizzando la ricorsione,
senza usare le sequenze di espressioni.

FB
Logged
Franco Barbanera
Moderator
Forumista Eroico
*****
Offline Offline

Posts: 2.622



WWW
« Reply #3 on: 09-06-2015, 10:20:33 »

% Funzione ausiliaria che date le liste delle forchette disponibili e delle
% richieste pendenti cerca di soddisfarle. Le richieste vengono consumate in
% ordine inverso (ovvero dalla fine della lista verso l'inizio).
% La funzione restituisce le liste aggiornate in base alle eventuali richieste
% soddisfatte.

Anche se la funzione ausiliaria funziona, il tutto e' un po' macchinoso.
Se dobbiamo gestire le richieste con una politica first-come first-served, allora realizziamo
una struttura dati coda FIFO con le relative operazioni.

FB
Logged
Franco Barbanera
Moderator
Forumista Eroico
*****
Offline Offline

Posts: 2.622



WWW
« Reply #4 on: 09-06-2015, 10:22:14 »

E cambiamo nome alla funzione
wastesometime!

Mangiare e pensare non sono perdite di tempo...  :-)

FB
Logged
Pages: [1]   Go Up
Print
Jump to: