extending standard behaviours
Vance Shipley
vances@REDACTED
Wed Apr 17 02:31:29 CEST 2002
OK, I see how to do this now. My new behaviour module will
look like a user to the gen_fsm behaviour and so it exports
the call backs that gen_fsm expects. It will look like a
behaviour to it's users so we export the same but possibly
extended interface as gen_fsm to our users.
I put this together and it seems to work brilliantly. This
gives me exactly what I wanted which is to be able to write
generic handlers in one place and handle the specifics in
the individual state hanlder modules. For instance when
we terminate the fxs_fsm module's terminate/3 function will
do it's own clean up (hang up a call in a signaling specific
way) and then call the cha_fsm terminate function to do the
common clean up tasks (write to a log). Messages received
by fxs_fsm which are not understood by it are forwarded on
to chan_fsm which handles them in a generic way.
Thanks Chris!
-Vance
-----------------------------------------------------------------------------
-module(chan_fsm).
-behaviour(gen_fsm).
% export the gen_fsm interface
-export([start/3, start/4,
start_link/3, start_link/4,
send_event/2, sync_send_event/2, sync_send_event/3,
send_all_state_event/2,
sync_send_all_state_event/2, sync_send_all_state_event/3,
reply/2]).
% behaviour modules must export this function
-export([behaviour_info/1]).
% export the gen_fsm call backs
-export([init/1, handle_event/3, handle_sync_event/4,
handle_info/3, terminate/3, code_change/4]).
%%
%% define what call backs users must export
%%
behaviour_info(callbacks) ->
% we add our own requirements to those of gen_fsm
[{idle, 2},{busy, 2}] ++ gen_fsm:behaviour_info(callbacks);
behaviour_info(Other) ->
gen_fsm:behaviour_info(Other).
%%
%% pass through functions to gen_fsm
%%
start(Mod, Args, Options) ->
gen_fsm:start(Mod, Args, Options).
start(Name, Mod, Args, Options) ->
gen_fsm:start(Name, Mod, Args, Options).
start_link(Mod, Args, Options) ->
gen_fsm:start_link(Mod, Args, Options).
start_link(Name, Mod, Args, Options) ->
gen_fsm:start_link(Mod, Args, Options).
send_event(Name, Event) ->
gen_fsm:send_event(Name, Event).
sync_send_event(Name, Event) ->
gen_fsm:sync_send_event(Name, Event).
sync_send_event(Name, Event, Timeout) ->
gen_fsm:sync_send_event(Name, Event).
send_all_state_event(Name, Event) ->
gen_fsm:send_all_state_event(Name, Event).
sync_send_all_state_event(Name, Event) ->
gen_fsm:sync_send_all_state_event(Name, Event).
sync_send_all_state_event(Name, Event, Timeout) ->
gen_fsm:sync_send_all_state_event(Name, Event, Timeout).
reply(Caller, Reply) ->
gen_fsm:reply(Caller, Reply).
%%
%% call backs
%%
init(Args) ->
process_flag(trap_exit, true),
io:fwrite("chan_fsm: OK, let's play!~n"),
{ok, idle, []}.
handle_event(Event, StateName, StateData) ->
io:fwrite("chan_fsm: Thank you for the ~w event.~n", [Event]),
{next_state, StateName, StateData}.
handle_sync_event(Event, From, StateName, StateData) ->
io:fwrite("chan_fsm: I don't handle sync events!~n"),
{reply, ignore, StateName, StateData}.
handle_info(Event, State, StateData) ->
io:fwrite("chan_fsm: Please use chan_fsm:send_event/2 to talk to me!~n"),
{next_state, State, StateData}.
terminate(Reason, State, StateData) ->
io:fwrite("chan_fsm: It's been fun. Bye.~n").
code_change(OldVersion, State, Data, Extra) ->
io:fwrite("chan_fsm: Nothing to do here.~n"),
{ok, State, Data}.
-----------------------------------------------------------------------------
-module(fxs_fsm).
-behaviour(chan_fsm).
% export the states
-export([idle/2, busy/2]).
% export the gen_fsm call backs
-export([init/1, handle_event/3, handle_sync_event/4,
handle_info/3, terminate/3, code_change/4]).
%%
%% states
%%
idle(Event, StateData) ->
io:fwrite("The fxs state machine got ~w in ~w~n", [Event, idle]),
{next_state, busy, StateData}.
busy(Event, StateData) ->
io:fwrite("The fxs state machine got ~w in ~w~n", [Event, busy]),
{next_state, idle, StateData}.
%%
%% call backs
%%
init(Args) ->
chan_fsm:init(Args).
handle_event(Event, StateName, StateData) ->
chan_fsm:handle_event(Event, StateName, StateData).
handle_sync_event(Event, From, StateName, StateData) ->
chan_fsm:handle_sync_event(Event, From, StateName, StateData).
handle_info(foo, State, StateData) ->
io:fwrite("The fxs state machine accepts your foo event~n"),
{next_state, State, StateData};
handle_info(bar, State, StateData) ->
io:fwrite("The fxs state machine accepts your bar event~n"),
{next_state, State, StateData};
handle_info(Event, State, StateData) ->
chan_fsm:handle_info(Event, State, StateData).
terminate(Reason, State, StateData) ->
io:fwrite("Here I would do any fxs specific clean up.~n"),
chan_fsm:terminate(Reason, State, StateData).
code_change(OldVersion, State, Data, Extra) ->
io:fwrite("Here I would do any fxs specific code change tasks.~n"),
chan_fsm:code_change(OldVersion, State, Data, Extra).
More information about the erlang-questions
mailing list