Hi, Vlad!
Try the following:
First the loop: (can be a single registered process (better than passing PIDs around) or
a stand alone gen_server (which has certain qualities you might wanna have in your module..)):
loop() ->
receive
{input, Data} ->
processInput(Data),
loop();
AnyMessage ->
store(AnyMessage),
loop
after 2300 ->
timeOutRoutine(),
loop()
end.
Then a loop-state in order to verify the loops' state and
to store messages that are not caught by the reseive-pattern:
State = [{active, true}, {pending, []}]
the adapted loop function and the list-related helperz:
loop(State) ->
receive
activate ->
NewState = replaceVariable(State, {active, true}),
loop(NewState);
deactivate ->
NewState = replaceVariable(State, {active, false}),
loop(NewState);
{input, Data} ->
case getValue(State, active) of
false ->
loop(State);
true ->
processInput(Data),
loop(State)
end;
AnyMessage ->
case getValue(State, active) of
false ->
loop(State);
true ->
%% now storing the msg in the loop's state:
NewState = replaceVariable(State, {pending, AnyMessage}),
loop(State)
end
after 2300 ->
timeOutRoutine(),
loop()
end.
%% getValue
getValue([], Key) ->
value_not_found;
getValue([{Key, Value}, Rest], Key) ->
Value;
getValue([{_OtherKey, _OtherValue}, Rest], Key) ->
getValue(Rest, Key).
%% replaceVariable
replaceVariable({SuperVarKey, VarList}, {VarKey, NewValue}) ->
{SuperVarKey, replaceVariable(VarList, {VarKey, NewValue})};
replaceVariable(VarList, {Key, Value}) ->
replaceVariable(VarList, {Key, Value}, []).
replaceVariable([], {_VarKey, _NewValue}, _Acc) ->
void;
replaceVariable([{VarKey, _OldValue} | Rest], {VarKey, NewValue}, Acc) ->
lists:append([ lists:append([Acc, [{VarKey, NewValue}]]), Rest]);
replaceVariable([{OtherVarKey, OtherValue} | Rest], {VarKey, NewValue}, Acc) ->
replaceVariable(Rest, {VarKey, NewValue}, lists:append([Acc, [{OtherVarKey, OtherValue}]])).
Obviously there are many ways to Rome, you can also use a dets/ets or mnesia to store wanted/unwanted messages instead of
saving it to the loop's state. Or you could use a gen_server instead that has some additional features with a native
server state that might suit your needs a lil' better.
Best Regards,
Christoph Grasl
Embedded Software Entwickler
KEYTRONIX
Gesellschaft für industrielle Elektronik und Informationstechnologie mbH
Ungargasse 64-66/1/109
A-1030 WIEN
E-Mail:
Tel.: +43 (1) 718 06 60 - 323
Mobil: +43 (664) 8556456
WWW: http://www.keytronix.com
HG Wien FN 261131t
Confidentiality Notice:
This message may contain privileged and confidential information. If you think, for any reason, that this message may have been addressed to you in error, you must not disseminate, copy or take any action in reliance on it, and we would ask you to notify us immediately by return email.
-----Ursprüngliche Nachricht-----
Von: im Auftrag von Vlad Dumitrescu
Gesendet: Di 05.08.2008 08:59
An: erlang-questions
Betreff: [erlang-questions] Selective receive issue
Hi all,
I have an example of a receive where I don't seem to be able to use the
usual "dump any unrecognized messages" catch-all clause. I think it is also
an example where channels could be useful, but the main question is whether
I am missing the obvious or not.
I have a process that takes {input, Data} messages from its mailbox and
processes them (not necessarily one at a time). Flow control is implemented
as a pair of 'start'/'stop' messages. The way I implemented the main loop is
(simplified)
receive
start->Running = true, loop();
stop->Running = false, loop()
after 0 ->
if Running -> process_one_step(), loop();
true -> loop()
end
end,
where the process_one_step() function may call
receive
{input, Data} -> ...
end
one or several times (it is configurable by the clients).
It seems to me that there is no place where I can put a '_->...;' clause
without creating problems. So I'd like to ask if anyone sees another way to
structure this that will allow rogue messages to be discarded.
------
A solution that requires an EEP :-) is to introduce an extension to the
receive statement that will explicitly keep matched messages in the
mailbox. For example
receive
Pattern -> keep(), loop();
Msg -> process(Msg), loop()
end
keep() is the extension that says "leave the message in the mailbox and
proceed". This way process() will be called with all messages except those
matching Pattern
Would something like that be useful, or are there already ways to achieve
the same effect?
best regards,
Vlad
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080805/10dc6923/attachment.html>