Desenvolva um módulo em Erlang que modelize uma estrutura master-slave em que o master garanta que os slaves se mantêm "vivos":
As funções a desenvolver são:
Instruções recomendadas:
Experimente esta solução que usa interface gráfica. Que diferenças nota em relação ao módulo desenvolvido? Que melhorias se poderiam incluir nesta solução e como?
-module(aula10).
-export([start/1, slave/0, to_slave/2]).
-define(MASTER, andy@pcigb10).
start( N ) ->
register( master, self() ),
process_flag(trap_exit, true ),
Lista_slaves = cria_slaves( N, [] ),
process_msgs( Lista_slaves ).
slave( ) ->
receive
die ->
true;
Msg ->
io:format("Mensagem recebida: ~w~n", [Msg]),
slave()
end.
process_msgs( Lista_slaves ) ->
receive
{ to_slave, Num_slave, Msg } ->
send_msg( Lista_slaves, Num_slave, Msg ),
process_msgs( Lista_slaves );
{ 'EXIT', Pid, Razao } ->
case recria_slave( Lista_slaves, Pid ) of
erro ->
io:format("Erro desconhecido~n", []),
process_msgs( Lista_slaves );
Lista_slaves_nova ->
io:format("processo ~w terminou por ~w, e foi recriado~n",[element(1, hd(Lista_slaves_nova)), Razao] ),
process_msgs( Lista_slaves_nova )
end
end.
cria_slaves( 0, L ) -> L;
cria_slaves( N, L ) ->
cria_slaves( N-1, [ { N, spawn_link(?MODULE, slave, []) } | L ] ).
recria_slave( Lista_slaves, Pid_slave ) ->
case [X || X <- Lista_slaves, element(2, X) == Pid_slave ] of
[ { Num_slave, Pid_slave } ] ->
NovoSlave = { Num_slave, spawn_link(?MODULE, slave, []) },
[ NovoSlave | [X || X <- Lista_slaves, element(2, X) =/= Pid_slave ] ];
_ ->
erro
end.
send_msg( Lista_slaves, Num_slave, Msg ) ->
case [ X || X <- Lista_slaves, element(1, X) == Num_slave ] of
[ {Num_slave, Pid_slave} ] ->
Pid_slave ! Msg;
_ ->
erro
end.
to_slave( Msg, N ) ->
{ master, ?MASTER } ! { to_slave, N, Msg }.
%% Copyright (C) 1996 Ericsson Software Technology AB, Erlang Systems
%% File : qes.erl
%% Author : Anders Dahlin <anders@erlang.ericsson.se>
%% Purpose : A solution to exercise 7.2 in the Introductory Course in Erlang
%% Created : 11 Oct 1996 by Anders Dahlin <anders@erlang.ericsson.se>
%% Modified: 25 Aug 1997 by Gunilla Hugosson <gunilla@erlang.ericsson.se>
-module(qes).
-author('anders@erlang.ericsson.se').
-export([start/0,init/1]).
start() ->
spawn(qes, init, [self()]).
init(Parent) ->
process_flag(trap_exit, true),
make_window(),
loop(Parent).
loop(Parent) ->
receive
{gs, quitBtn, click, Data, Args} ->
exit(normal);
{gs, spawnBtn, click, Data, Args} ->
spawn_link(qes, init, [self()]),
loop(Parent);
{gs, errorBtn, click, Data, Args} ->
exit(error);
{'EXIT', Parent, Reason} ->
exit(Reason);
{'EXIT', From, normal} ->
loop(Parent);
{'EXIT', From, Reason} ->
spawn_link(qes, init, [self()]),
loop(Parent)
end.
%% ----------------------------------------------------------------------
%% Opens a window with three buttons for
%% QUIT: Closes window and all child windows
%% SPAWN: Spawns of a child window
%% ERROR: Dies because of an error, all children will also die.
%% The window should be restarted by the parent window.
%% Title of the window will be the pid of the calling process.
%% The calling process will receive messages when a button is pressed.
%% Messages look like:
%% {gs, ButtonName, click, _Data, _Args}
%% where ButtonName is: quitBtn, spawnBtn or errorBtn
%% Returns: ok
%% ----------------------------------------------------------------------
make_window() ->
W = gs:create(window, gs:start(), [{width,150}, {height,30}]),
Q = gs:create(button, quitBtn, W, [{bg, green}, {width,50}, {x,0}, {y,0},
{label, {text, "Quit"}}]),
S = gs:create(button, spawnBtn, W, [{bg, lightblue}, {width,50}, {x,50},
{y,0}, {label, {text, "Spawn"}}]),
E = gs:create(button, errorBtn, W, [{bg, red}, {width,50}, {x,100}, {y,0},
{label, {text, "Error"}}]),
gs:config(W, [{title, pid_to_list(self())}, {map, true}]), ok.
Última actualização: 18 Abr 2005