2012-04-15 11 views
0

Ich möchte eine Reihe von Prozessen spawnen, die auf Nachrichten reagieren, die sie erhalten. Das ist einfach. Ich möchte aber auch einen Prozess haben, der die Ausgabe eines anderen Prozesses blockieren kann.Erlang Process Message Suppression

In einer anderen Sprache könnte ich ein Flag setzen und den Status dieses Flags vor dem Senden einer Nachricht überprüfen. Aber da Erlang keine veränderlichen Variablen hat, wie kann ich das erreichen?

Ich kann sicherlich ein Muster in einer receive hinzufügen, um nach einer Unterdrückung Nachricht zu beobachten. Ich weiß einfach nicht, was ich als nächstes machen soll.

Ich mag nicht wirklich die Idee, eine ETS-Tabelle nur dafür zu verwenden, da das ein nettes verteiltes Modell bricht. Gleichermaßen interessiere ich mich nicht so sehr für Nebenläufigkeitsprobleme, aber ich möchte dies auf die am besten geeignete Weise gestalten.

+0

einen Flag im Prozessdaten halten, die anzeigt, ob es sich um Nachrichten zu senden oder nicht. – rvirding

Antwort

2

Jeder Echo-Server kann einen eigenen Status haben, der angibt, ob er gerade stummgeschaltet ist. Andere Prozesse können diesen Status mit Mute-/Unmute-Nachrichten umschalten. Bevor der Echo-Server auf eine Nachricht antwortet, überprüft er den Status und reagiert entsprechend.

Zum Beispiel:

1> {ok, Pid} = echo:start_link(). 
{ok,<0.99.0>} 
2> echo:echo(Pid, "this message will be echoed."). 
#Ref<0.0.0.443> 
3> echo:echo(Pid, "as will this message.."). 
#Ref<0.0.0.447> 
4> echo:mute(Pid). 
ok 
5> echo:echo(Pid, "this message will not."). 
#Ref<0.0.0.457> 
6> echo:unmute(Pid). 
ok 
7> echo:echo(Pid, "but this one will.."). 
#Ref<0.0.0.461> 
8> flush(). 
Shell got {#Ref<0.0.0.443>,"this message will be echoed."} 
Shell got {#Ref<0.0.0.447>,"as will this message.."} 
Shell got {#Ref<0.0.0.461>,"but this one will.."} 
ok 
9> echo:stop(Pid). 
ok 

Code:

-module(echo). 

-behaviour(gen_server). 

%% API 
-export([start_link/0, 
    echo/2, 
    mute/1, 
    unmute/1, 
    stop/1]). 

%% gen_server callbacks 
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, 
    terminate/2, code_change/3]). 

-define(SERVER, ?MODULE). 

-record(state, {mute=false}). 

%%%=================================================================== 
%%% API 
%%%=================================================================== 

start_link() -> 
    gen_server:start_link(?MODULE, [], []). 

echo(Pid, Msg) -> 
    Ref = make_ref(), 
    gen_server:cast(Pid, {echo, self(), Ref, Msg}), 
    Ref. 

mute(Pid) -> 
    gen_server:cast(Pid, mute). 

unmute(Pid) -> 
    gen_server:cast(Pid, unmute). 

stop(Pid) -> 
    gen_server:cast(Pid, stop). 

%%%=================================================================== 
%%% gen_server callbacks 
%%%=================================================================== 

init([]) -> 
    {ok, #state{}}. 

handle_call(_Request, _From, State) -> 
    Reply = ok, 
    {reply, Reply, State}. 

handle_cast({echo, From, Tag, Msg}, #state{mute=false} = State) -> 
    From ! {Tag, Msg}, 
    {noreply, State}; 
handle_cast({echo, _From, _Tag, _Msg}, #state{mute=true} = State) -> 
    {noreply, State}; 
handle_cast(mute, State) -> 
    {noreply, State#state{mute=true}}; 
handle_cast(unmute, State) -> 
    {noreply, State#state{mute=false}}; 
handle_cast(stop, State) -> 
    {stop, normal, State}; 
handle_cast(_Msg, State) -> 
    {noreply, State}. 

handle_info(_Info, State) -> 
    {noreply, State}. 

terminate(_Reason, _State) -> 
    ok. 

code_change(_OldVsn, State, _Extra) -> 
    {ok, State}.