"Forwarding" of gen_server calls?

Jim Larson jim@REDACTED
Fri Sep 17 02:02:21 CEST 1999


I'm using using open-source Erlang (erlang_base-47.4.1) on FreeBSD
2.2.8.

I'm writing a server S1 using the gen_server behaviour.  One of
the handle_call() clauses makes a "tail call" to server S2 (which
also uses gen_server), i.e.

    handle_call(Request, From, State) ->
        %% ... some pre-processing goes on ...
        Reply = gen_server:call(S2, Arg),
        {reply, Reply, NewState}

However, the call to S2 may block for a long period of time, thus
blocking all calls to S1 in the interim.

What would be nice is a "tail call" function in the gen_server
package that would allows you to forward the From "continuation"
to another gen_server module, but returns to its caller immediately.

    handle_call(Request, From, State) ->
        %% ... the same pre-processing goes on ...
        %% This call won't block
        case gen_server:tail_call(S2, Arg, From) of
            ok ->
                {noreply, NewState}; % S2 will reply to our caller
            {error, Reason} ->
                %% error looking up S2
                {reply, {error, SomeReason}, SomeState}
        end.

The implementation for the simplest clause of tail_call would be
something like:

    tail_call(Pid, Request, From) when pid(Pid), node(Pid) == node() ->
        Pid ! {'$gen_call', From, Request},
        ok.

[Okay, so it doesn't quite handle all error cases, since the original
gen_server caller will only catch 'EXIT' messages from the Pid of
the server it originally called.  I'm sure there are ways to deal
with this.]

I realize that there are other workarounds, including:

	- returning appropriate information from S1, and
	  allowing the original client process to call S2;

	- having S1 spawn a new process to make the blocking call;

	- explicitly passing the From "continuation" as an
	  argument to a special method of S2.

However, these workarounds are unappealing.  Am I overlooking any
other options or existing infrastructure for accomplishing what I
want?

I await the comments of those wiser in the ways of Erlang than I.

Jim



More information about the erlang-questions mailing list