gen_fsm:send_after | start_timer

Francesco Cesarini <>
Mon Jul 9 18:11:03 CEST 2001


Hi Sean,
why don't you use timer:apply_after/4 and create your own timeout events?

%% Called when you set the timer.
timer(Ms) ->
        timer:apply_after(Ms, ?MODULE, timeout, [self()]).

%% Call back function
timeout(GenFsg) ->
    gen_fsm:send_event(GenFSM, timeout).

Regards,
Francesco
--
http://www.erlang-consulting.com

Sean Hinde wrote:

> Hi,
>
> Anyone else think it would be useful to extend gen_fsm to have it's own
> state aware timer functionality?
>
> At the moment all timers sent with erlang:send_after or erlang:start_timer
> arrive in handle_info rather than in the callback for the current state. I
> find that handle_info becomes very large and unwieldy with more than a
> couple of timers running and 4 or more states..
>
> Usage would be something like:
>
> %%----------------------------------------------------------------------
> %% Func: init/1
> %% Returns: {ok, StateName, StateData}          |
> %%          {ok, StateName, StateData, Timeout} |
> %%          ignore                              |
> %%          {stop, StopReason}
> %%----------------------------------------------------------------------
> init([]) ->
>     gen_fsm:start_timer(2000, "Hello from init"),
>     {ok, state1, #state{}}.
>
> %%----------------------------------------------------------------------
> %% Func: StateName/2
> %% Returns: {next_state, NextStateName, NextStateData}          |
> %%          {next_state, NextStateName, NextStateData, Timeout} |
> %%          {stop, Reason, NewStateData}
> %%----------------------------------------------------------------------
> state1(Event, StateData) ->
>     gen_fsm:start_timer(2000, "Hello from state 1"),
>     io:format("SH:~p~n",[Event]),
>     {next_state, state2, StateData}.
>
> state2(Event, StateData) ->
>     io:format("SH:~p~n",[Event]),
>     gen_fsm:send_after(2000, "Hello from state 2"),
>     {next_state, state1, StateData}.
>
> Possible implementation follows as a diff -c:
>
> *** /opt/rcs/5.0.2.5/lib/stdlib-1.9.4/src/gen_fsm.erl   Thu Jun  7 15:04:40
> 2001
> --- gen_fsm.erl Mon Jul  9 13:14:09 2001
>
> ***************
>
> *** 110,115 ****
>
> --- 110,117 ----
>
>          sync_send_all_state_event/2, sync_send_all_state_event/3,
>
>          reply/2]).
>
>
>
> + -export([start_timer/2, send_after/2]).
>
> +
>
>   %% Internal exports
>
>   -export([init_it/6, print_event/3,
>
>          system_continue/3,
>
> ***************
>
> *** 199,204 ****
>
> --- 201,217 ----
>
>                            [Name, Event, Timeout]}})
>
>       end.
>
>
>
> + %% Designed to be only callable within one of the callbacks
>
> + %% hence using the self() of this instance of the process.
>
> + %% This is to ensure that timers don't go astray in global
>
> + %% e.g. when straddling a failover, or turn up in a restarted
>
> + %% instance of the process.
>
> + start_timer(Time, Msg) ->
>
> +     erlang:start_timer(Time, self(), {'$gen_fsm_timer', Msg}).
>
> +
>
> + send_after(Time, Msg) ->
>
> +     erlang:send_after(Time, self(), {'$gen_fsm_timer', Msg}).
>
> +
>
>   %%% ---------------------------------------------------
>
>   %%% Initiate the new process.
>
>   %%% Register the name using the Rfunc function
>
> ***************
>
> *** 288,293 ****
>
> --- 301,314 ----
>
>             io:format(Dev,
>
>                       "*DBG* ~p got all_state_event ~p in state ~w~n",
>
>                       [Name, Event, StateName]);
>
> +       {'$gen_fsm_timer', Msg} ->
>
> +           io:format(Dev,
>
> +                     "*DBG* ~p got timer ~p in state ~w~n",
>
> +                     [Name, Msg, StateName]);
>
> +       {timeout, Ref, {'$gen_fsm_timer', Msg}} ->
>
> +           io:format(Dev,
>
> +                     "*DBG* ~p got timer ~p in state ~w~n",
>
> +                     [Name, {timeout, Ref, Msg}, StateName]);
>
>         _ ->
>
>             io:format(Dev, "*DBG* ~p got ~p in state ~w~n",
>
>                       [Name, Msg, StateName])
>
> ***************
>
> *** 367,372 ****
>
> --- 388,397 ----
>
>   dispatch({'$gen_sync_all_state_event', From, Event},
>
>          Mod, StateName, StateData) ->
>
>       apply(Mod, handle_sync_event, [Event, From, StateName, StateData]);
>
> + dispatch({'$gen_fsm_timer', Msg}, Mod, StateName, StateData) ->
>
> +     apply(Mod, StateName, [Msg, StateData]);
>
> + dispatch({timeout, Ref, {'$gen_fsm_timer', Msg}}, Mod, StateName,
> StateData) -
> >
>
> +     apply(Mod, StateName, [{timeout, Ref, Msg}, StateData]);
>
>   dispatch(Info, Mod, StateName, StateData) ->
>
>       apply(Mod, handle_info, [Info, StateName, StateData]).
>
>
>
> ***************
>
> *** 423,428 ****
>
> --- 448,457 ----
>
>       "** Last event in was ~p (for all states)~n";
>
>   get_msg_str({'$gen_sync_all_state_event', Event}) ->
>
>       "** Last sync event in was ~p (for all states)~n";
>
> + get_msg_str({'$gen_fsm_timer', Msg}) ->
>
> +     "** Last timer event in was ~p~n";
>
> + get_msg_str({timeout, Ref, {'$gen_fsm_timer', Msg}}) ->
>
> +     "** Last timer event in was ~p~n";
>
>   get_msg_str(Msg) ->
>
>       "** Last message in was ~p~n".
>
>
>
> ***************
>
> *** 430,435 ****
>
> --- 459,466 ----
>
>   get_msg({'$gen_sync_event', Event}) -> Event;
>
>   get_msg({'$gen_all_state_event', Event}) -> Event;
>
>   get_msg({'$gen_sync_all_state_event', Event}) -> Event;
>
> + get_msg({'$gen_fsm_timer', Msg}) -> Msg;
>
> + get_msg({timeout, Ref, {'$gen_fsm_timer', Msg}}) -> {timeout, Ref, Msg};
>
>   get_msg(Msg) -> Msg.
>
>
>
>   %%-----------------------------------------------------------------
>
>
>
> - Sean
>
> NOTICE AND DISCLAIMER:
> This email (including attachments) is confidential.  If you have received
> this email in error please notify the sender immediately and delete this
> email from your system without copying or disseminating it or placing any
> reliance upon its contents.  We cannot accept liability for any breaches of
> confidence arising through use of email.  Any opinions expressed in this
> email (including attachments) are those of the author and do not necessarily
> reflect our opinions.  We will not accept responsibility for any commitments
> made by our employees outside the scope of our business.  We do not warrant
> the accuracy or completeness of such information.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: francesco.vcf
Type: text/x-vcard
Size: 352 bytes
Desc: Card for Francesco Cesarini
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20010709/1464ff12/attachment.vcf>


More information about the erlang-questions mailing list