Multiple behaviour processes
Vance Shipley
vances@REDACTED
Thu Jan 6 14:08:53 CET 2005
On Thu, Jan 06, 2005 at 02:25:09PM +0200, Yoel Jacobsen wrote:
some icky html stuff
What I do is to create a my_fsm.erl bahaviour module which exports
the same interface as gen_fsm. You create a function for each of
the exports and have it call gen_fsm's functions.
send_event(FsmRef, Event) ->
gen_fsm:send_event(FsmRef, Event).
So now you have a new my_fsm which behaves identically to
gen_fsm. It should also export behaviour_info:
behaviour_info(callbacks) ->
gen_fsm:behaviour_info(callbacks);
behaviour_info(Other) ->
gen_fsm:behaviour_info(Other).
You can use this in the same way as gen_fsm so if you have a
gen_fsm behaviour module named foo_fsm.erl you can just change
the -behaviour(gen_fsm) to -behaviour(my_fsm) and start it using
my_fsm:
my_fsm:start(foo_fsm, Args, Options)
Now you modify it's behaviour to suit. Firstly let's have
it keep it's own state. We'll modify the start functions:
start(Module, Args, Options) ->
gen_fsm:start(?MODULE, [Module, Args], Options).
init(init([Module, Args]) ->
case Module:init(Args) of
{ok, StateName, StateData} ->
{ok, statename, #state{module = Module, data = StateData}};
{ok, StateName, StateData, Timeout} ->
{ok, statename, #state{module = Module, data = StateData}, Timeout};
{stop, Reason} ->
{stop, Reason};
ignore ->
ignore;
Other ->
Other
end.
And we'll have one or more private states. Here I made just
one named statename. You create specific state handlers to handle
just the events you're interested in and the rest are passed through:
statename(Event, From, State) ->
Module = State#state.module,
StateName = State#state.statename,
case Module:StateName(Event, From, State#state.statedata) of
{reply, Reply, NextStateName, NewStateData} ->
NewState = State#state{statename = NextStateName,
statedata = NewStateData},
{reply, Reply, statename, NewState};
{reply, Reply, NextStateName, NewStateData, Timeout} ->
NewState = State#state{statename = NextStateName,
statedata = NewStateData},
{reply, Reply, statename, NewState, Timeout};
{next_state, NextStateName, NewStateData} ->
NewState = State#state{statename = NextStateName,
statedata = NewStateData},
{next_state, statename, NewState};
{next_state, NextStateName, NewStateData, Timeout} ->
NewState = State#state{statename = NextStateName,
statedata = NewStateData},
{next_state, statename, NewState, Timeout};
{stop, Reason, Reply, NewStateData} ->
NewState = State#state{statedata = NewStateData},
{stop, Reason, Reply, NewState};
{stop, Reason, NewStateData} ->
NewState = State#state{statedata = NewStateData},
{stop, Reason, NewState};
Other ->
Other
end.
I use this method in my LAPD protocol stack to allow users to
easily adapt the lapd_mux_fsm to different layer 1 implementations.
http://www.motivity.ca/lapd/lapd_mux_fsm.html
-Vance
Vance Shipley
Motivity Telecom Inc.
vances@REDACTED
More information about the erlang-questions
mailing list