How to 'bypass' the receive timer
Ulf Wiger
etxuwig@REDACTED
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