How to 'bypass' the receive timer

Ulf Wiger <>
Fri Feb 8 15:26:56 CET 2002


On Fri, 8 Feb 2002, Faustin Ngokse wrote:

>Hello erlang friends,
>
>This is my first contribution on this mailing list, I guess I
>am at the right place.
>I have an erlang process working as server and receiving a lot
>of messages. Some messages trigger further "receive" with a
>timer to prevent the process from waiting undefinetely.
>It often happens that the messages destinated to the 'external'
>receive can't be delivered because the timer for the 'internal'
>receiver is not yet over. This make my server process very very
>slow.
>Is there a possibility to influence the message so that
>messages for the 'external' receive can be delivered while the
>'internal' receive is still waiting?
>Do anybody have another idea how to solve this problem?


I am not altogether sure that I understand your problem
correctly. Basically, your server tends to get stuck in blocking
receive while servicing client requests, right?

If so, there are a couple of ways to address the problem:

- Have the server spawn a request thread for each incoming
  request, or at least those requests that might take a long
  time. The OTP rpc.erl module is implemented this way.
  You may want to think about partitioning your server state if
  the request threads need to share state. I have a fairly clean
  example of how to do this that I may post shortly.  ;)

- Keep a 'pending' list where you can save the request, and
  convert the blocking operations on the server side to non-
  blocking. This can get a bit envolved. Below is a simplified
  example, which makes some assumptions, and doesn't handle
  error conditions.


   handle_call({...} = Req, Ref, State) ->
      Sofar = ...,
      NewState = non_blocking_call(OtherServer, MyReq, Ref,
                                   Req, Sofar, State),
      {noreply, NewState}.

   handle_cast({nb_reply, Ref, Reply},
               #state{pending = Pending} = State0) ->
      {value, {Ref, Sofar, ClientReq}} =
         lists:keysearch(Ref, 1, Pending),
      State1 = State#state{pending = lists:keydelete(
                                        Ref, 1, Pending),
      {Reply, State2} = finish_request(ClientReq, Sofar,
                                         State1),
      {reply, Reply, State2}.

   non_blocking_call(Server, Req, Ref, ClientReq,
                     Sofar, #state{pending = Pending} = State) ->
      gen_server:cast(Server, {nb_req, self(), From, Req}),
      State#state{pending = [{Ref, Sofar, ClientReq}|Pending]}.


/Uffe




More information about the erlang-questions mailing list