[erlang-questions] Generic server and selective receives

Siraaj Khandkar <>
Mon Feb 17 08:40:44 CET 2014


With gen_server, you have no choice but to handle a message. Once you
have it, you can defer processing by stashing it in your process' state.
If you want to reject messages when client_pid=undefined, then you may
want to consider a protocol with receipt acknowledgements, notifying the
sender if the message was accepted or discarded.


On 2/16/14, 6:55 PM,  wrote:
> Hi,
> 
> I would like some help to implement a message-buffer in erlang. This
> process can be sent messages, and stores them in mailbox. A buffer can
> have one client, or can have no client. When there's no client, I
> would prevent the process to do anything but accept a new client or
> timeout after a small amount of time. So I have two sets of receive
> clauses.
> 
> Now, I would like to implement this as a gen_server. But I don't know
> how. The Idea is to timeout quickly if no message of the expected
> clauses-set comes.
> 
> * I thought of a gen_fsm but it will crash if it's sent a message when
> in the "no client" state, right ? (Plus i may want to handle more
> receive clauses in the "no client" part)
> * I thougt about time calculations but it's seems too complicated for
> no reason ; I prefer use the simple gen_* timeouts.
> * I could keep my current implementation and adapt the module to fit
> in a supervision tree but I believe I willll miss common OTP features.
> 
> So, I hope this is a common pattern and that someone will tell me a
> good solution.
> 
> Thank you.
> 
> -- lud
> 
> This is my current implementation (but not the actual code).
> 
>     loop(#state{client_pid=undefined}) ->
>         receive
>             {set_client,Pid} ->
>                 loop(State#state{client_pid=Pid})
>         after 10000 ->
>             io:fwrite("Terminating\n")
>         end;
> 
>     loop(State=#state{client_pid=Client,mailbox=Mailbox}) ->
>         receive
>             {set_client,Pid} ->
>                 %% here we can change the client or set it to undefined
>                 loop(State#state{client_pid=Pid});
>             {message,M} ->
>                 Client ! you_have_messages,
>                 loop(State#state{mailbox=[M|Mailbox]});
>             %% A handful of other clauses
>             ...
>                 ...
>                 ...
>         after way more time than 1000 ->
>             io:fwrite("Terminating too\n")
>         end;
> 
> 
> Now i'll pray for this mail to be seen in the current huge amount of
> emails (and very intersting by the way) on the list.


More information about the erlang-questions mailing list