Baseado no exercício da aula anterior, altere-o de forma que:
Funções e librarias a usar:
% as alterações para responder ao ponto 1 sao apresentadas a verde % as alterações para responder ao ponto 2 sao apresentadas a vermelho
% define uma constante denominada FILENAME com o valor aula6 -define(FILENAME, aula6).
% especifica o nome do módulo como sendo aula6 -module(?FILENAME).
-export([start/1, top/0, consultar/1, consultar/2, votar/2]).
start(No) -> spawn(No, ?FILENAME, top, []).
top() ->
register(top, self()),
Bandas = dict:new(),
Votantes = dict:new(),
top_processo(Bandas, Votantes).
top_processo(Bandas, Votantes) ->
receive
{ consultar, Ref, Requisitante } ->
Requisitante ! { consultar_resposta, Ref, Bandas },
top_processo(Bandas, Votantes);
{ consultar, Ref, Requerente, Banda } ->
case dict:find(Banda, Bandas) of
error -> Val = 0;
{ok, V} -> Val = V
end,
Requerente ! { consultar_resposta, Ref, {Banda, Val} },
top_processo(Bandas, Votantes);
{ votar, Ref, Votante, Banda } ->
% verifica se este PID ja votou
case dict:find(Votante, Votantes) of
error ->
% se ainda nao votou, pode votar
case dict:find(Banda, Bandas) of
error -> Val = 1;
{ok, V} -> Val = V + 1
end,
BandasNovo = dict:store(Banda, Val, Bandas),
VotantesNovo = dict:store(Votante, [], Votantes),
Votante ! {votar_resposta, Ref, {Banda, Val} },
top_processo(BandasNovo, VotantesNovo);
{ok, _} ->
% se ja votou, nao pode votar mais
Votante ! {votar_resposta, Ref, ja_votou },
top_processo(Bandas, Votantes)
end
end.
% por cada mensagem de consulta e gerada uma referencia % que sera posteriormente devolvida por top/0 para autenticar % a mensagem recebida.
consultar(Top) ->
Ref = make_ref(),
Top ! {consultar, Ref, self() },
receive
{ consultar_resposta, Ref, Resultado } -> Resultado
end.
consultar(Top, Banda) ->
Ref = make_ref(),
Top ! { consultar, Ref, self(), Banda},
receive
{ consultar_resposta, Ref, Resultado } -> Resultado
end.
% por cada mensagem enviada, gera uma referencia que guarda numa lista. % essa lista vai sendo criada a cada chamada de emite_votos/3. % a lista e retornada para votar/2 e sera usada em recebe_respostas/2 % para confirmar a autenticidade da mensagem recebida.
votar(Top, ListaBandas) ->
%% ponto 1
Refs = emite_votos(Top, ListaBandas, []),
recebe_respostas(ListaBandas, Refs).
emite_votos(_, [], Refs ) ->
io:fwrite("todos os votos foram emitidos~n"),
Refs;
emite_votos(Top, [H|ListaBandas], Refs ) ->
Refs = make_ref(),
Top ! { votar, Ref, self(), H },
emite_votos( Top, ListaBandas, [Ref|Refs] ).
recebe_respostas([], []) -> true;
recebe_respostas( [H|ListaBandas], [Ref|Refs] ) ->
recebe_respostas( ListaBandas, Refs ),
receive
{ votar_resposta, Ref, Resultado } -> io:fwrite("~s~n", [io_lib:write(Resultado)]);
{ votar_resposta, Ref, ja_votou } -> io:fwrite("ja votou.")
end.

Última actualização: 14 Março 2000