[erlang-questions] Best practices in gen_fsm usage
Vance Shipley
vances@REDACTED
Tue Dec 13 10:33:56 CET 2011
On Tue, Dec 13, 2011 at 12:38:51AM -0800, Steve Davis wrote:
} I need to figure out why I end up with a gen_server after starting
} out with a gen_fsm, and then may have something more fruitful to say.
One good reason to migrate a gen_fsm to gen_server is that it becomes
clear that it has no unique states. In my experience it is much more
common to migrate a gen_server to a gen_fsm as it becomes clear that
there are unique states. The following provides a contrived example.
Start with a gen_server:
-module(foo_server).
-export([init/1, handle_call/3]).
-behaviour(gen_server).
-record(state, {sap}).
init(_Args) ->
{ok, #state{}}.
handle_call(bind, From, State) ->
SAP = bind(),
{reply, ok, State#state{sap = SAP}};
handle_call(get, From, #state{sap = SAP} = State) ->
Got = get(SAP),
{reply, Got, State}.
Later realize that binding may take time and have varying results:
-module(foo_fsm).
-export([init/1, idle/3, binding/2, bound/3]).
-behaviour(gen_fsm).
-record(statedata, {sap, from}).
init(_Args) ->
{ok, idle, #statedata{}}.
idle(bind, From, Statedata) ->
bind(),
{next_state, binding, Statedata#statedata{from = From}}.
binding({error, Reason}, #statedata{from = From} = Statedata) ->
gen_fsm:reply(From, {error, Reason}),
{next_state, idle, #statedata{}};
binding(SAP, #statedata{from = From} = Statedata) ->
gen_fsm:reply(From, ok),
{next_state, bound, Statedata#statedata{sap = SAP}}.
bound(get, From, #statedata{sap = SAP} = Statedata) ->
Got = get(SAP),
{reply, Got, bound, Statedata}.
--
-Vance
More information about the erlang-questions
mailing list