<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Generator" CONTENT="MS Exchange Server version 6.5.7653.38">
<TITLE>AW: [erlang-questions] Selective receive issue</TITLE>
</HEAD>
<BODY>
<!-- Converted from text/plain format -->

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

</BODY>
</HTML>