gen_fsm:send_after | start_timer

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

gen_fsm:send_after | start_timer

Sean Hinde-2
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.




Reply | Threaded
Open this post in threaded view
|

gen_fsm:send_after | start_timer

Francesco Mazzoli-2
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>

Reply | Threaded
Open this post in threaded view
|

silly question: erlang pronunciation

Garry Hodgson-3
In reply to this post by Sean Hinde-2

i'm giving a talk soon on our use of erlang, and it occurred to me
that i'm not sure how it is pronounced.  is it prounounced like
"air-lang",
or "ir-lang"?  i've heard both.

thanks

--
Garry Hodgson                   sometimes we ride on your horses
Senior Hacker                   sometimes we walk alone
Software Innovation Services    sometimes the songs that we hear
AT&T Labs                       are just songs of our own
garry


Reply | Threaded
Open this post in threaded view
|

silly question: erlang pronunciation

Matthias Lang-2

 > i'm giving a talk soon on our use of erlang, and it occurred to me
 > that i'm not sure how it is pronounced.  is it prounounced like
 > "air-lang", or "ir-lang"?  i've heard both.

Native English speakers tend to call it "ir-lang" (i.e. sounds like
'herlang' said by someone 'oo drops 'is aitches) whereas the Swedes
make it sound more like "air-lang", especially when they're speaking
Swedish.

Matt


Reply | Threaded
Open this post in threaded view
|

silly question: erlang pronunciation

Luke Gorrie-3
matthias writes:

>  > i'm giving a talk soon on our use of erlang, and it occurred to me
>  > that i'm not sure how it is pronounced.  is it prounounced like
>  > "air-lang", or "ir-lang"?  i've heard both.
>
> Native English speakers tend to call it "ir-lang" (i.e. sounds like
> 'herlang' said by someone 'oo drops 'is aitches) whereas the Swedes
> make it sound more like "air-lang", especially when they're speaking
> Swedish.

To avoid confusion, maybe it should be renamed ?rlang ;-)

Cheers,
Luke



Reply | Threaded
Open this post in threaded view
|

silly question: erlang pronunciation

Garry Hodgson-3
In reply to this post by Matthias Lang-2
matthias wrote:
>
>  > i'm giving a talk soon on our use of erlang, and it occurred to me
>  > that i'm not sure how it is pronounced.  is it prounounced like
>  > "air-lang", or "ir-lang"?  i've heard both.
>
> Native English speakers tend to call it "ir-lang" (i.e. sounds like
> 'herlang' said by someone 'oo drops 'is aitches) whereas the Swedes
> make it sound more like "air-lang", especially when they're speaking
> Swedish.

i expect i'll keep calling it "air-lang" then, in deference to my
swedish
great grandmother.

thanks to all who replied.

--
Garry Hodgson                   sometimes we ride on your horses
Senior Hacker                   sometimes we walk alone
Software Innovation Services    sometimes the songs that we hear
AT&T Labs                       are just songs of our own
garry


Reply | Threaded
Open this post in threaded view
|

silly question: erlang pronunciation

Robert Virding-4
In reply to this post by Luke Gorrie-3
Luke Gorrie <luke> writes:

>matthias writes:
>
>>  > i'm giving a talk soon on our use of erlang, and it occurred to me
>>  > that i'm not sure how it is pronounced.  is it prounounced like
>>  > "air-lang", or "ir-lang"?  i've heard both.
>>
>> Native English speakers tend to call it "ir-lang" (i.e. sounds like
>> 'herlang' said by someone 'oo drops 'is aitches) whereas the Swedes
>> make it sound more like "air-lang", especially when they're speaking
>> Swedish.
>
>To avoid confusion, maybe it should be renamed ?rlang ;-)

Great!  Then we can have .?rl files.  :-)

        Robert