[erlang-questions] Generic server and selective receives
Vance Shipley
vances@REDACTED
Mon Feb 17 06:15:08 CET 2014
On Mon, Feb 17, 2014 at 12:55:19AM +0100, ludovic@REDACTED wrote:
} 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)
In the example below it will crash if anything but a '{set_client, Pid}'
event is received during the 'wait_for_client' state but until you define
what it should do that is fine. If it should handle additional events
add clauses to wait_for_client/2.
} * I thougt about time calculations but it's seems too complicated for
} no reason ; I prefer use the simple gen_* timeouts.
It's not.
} * 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.
Unless you reimplement most of gen.erl you certainly will.
-module(mbox_fsm).
-behaviour(gen_fsm).
-export([init/1, handle_event/3, handle_sync_event/4, handle_info/3,
terminate/3, code_change/4]).
-export([wait_for_client/2, wait_for_request/2]).
-define(MAXTIME, 60000).
-record(statedata, {client_pid, mailbox = [], timeout}).
init(_Arg) ->
process_flag(trap_exit, true),
{ok, wait_for_client, #statedata{}, 10000}.
wait_for_client({set_client, Pid}, StateData) ->
NextStateData = StateData#statedata{client_pid = Pid},
{next_state, wait_for_request, NextStateData, ?MAXTIME}.
wait_for_request({set_client, Pid},
#statedata{timeout = Then} = StateData) ->
NextTimeout = ?MAXTIME - timer:now_diff(os:timestamp(), Then),
NextStateData = StateData#statedata{client_pid = Pid,
timeout = NextTimeout},
{next_state, wait_for_request, NextStateData, NextTimeout};
wait_for_request({message, M},
StateData#statedata{mailbox = Mailbox, timeout = Then}) ->
NextTimeout = ?MAXTIME - timer:now_diff(os:timestamp(), Then),
NextStateData = StateData#statedata{{mailbox = [M | Mailbox]},
{next_state, wait_for_request, NextStateData, NextTimeout};
% A handful of other clauses
wait_for_request(timeout, StateData) ->
{stop, timeout, StateData}.
handle_info(Info, _StateName, StateData) ->
{stop, Info, StateData}.
terminate(_Reason, _StateName, _StateData) ->
ok.
code_change(_OldVsn, StateName, StateData, _Extra) ->
{ok, StateName, StateData}.
--
-Vance
More information about the erlang-questions
mailing list