[erlang-questions] gen_fsm - timeout ?

Matthew Reilly <>
Tue Sep 19 20:15:42 CEST 2006

One way to do this is to store an absolute timeout time in your FSM
state and recalculate the relative timeout value everytime you chose the
next state.

%%%%%%%%%%%%%%%% Example %%%%%%%%%%%%%%%%%%%%%%
%% This intializes a FSM with a timeout time in seconds

-record(state, {
  timeout      %% Stores the absolute timeout time in {Mega,Sec,Micro} 
               %% format

init(TimeOutSeconds) ->
  {Mega,Sec,Micro} = now(),
  %% Calculate a timestamp which is TimeOutSeconds from now.
  %% The new seconds may exceed 1,000,000, but that is OK.
  Timeout = {Mega,Sec+TimeOutSecs,Micro},   
  State = #state{ stuff = <some stuff>, timeout = Timeout},
  {ok, next_state1, State, timeout(State)}.

%% Always calculate the timeout w/ timeout(State):
next_state1(Message, State) ->
  {next_state, next_state2, State, timeout(State)}.


%% Returns the difference between now() and the timeout in the state in 
%% milliseconds. Note, timer:now_diff/2 returns the time difference
%% between two {Mega,Sec,Micro} times (which is the format returned by
%% erlang:now/0). The difference is in microseconds.
timeout(State) ->
  case timer:now_diff(State#state.timeout,now()) of
      Diff when Diff < 0 -> 0;
      Diff -> Diff/1000

The advantage of this over creating a separate PID which sends a message
at a certain time is that you can update the timeout time just by
updating the timeout member of your state (as opposed to stopping the
separate PID, clear any possible pending timeout messages, and starting
a new one with a new timeout value).

On Tue, 2006-09-19 at 13:41 +0530, Sanjaya Vitharana wrote:
> Hi ... ALL,
> Behavior: Gen FSM
> Scenario:
> Want to be in state "open" (see below) for limited time (assume 5 sec)
> until some EXPECTED event (as_E) comes, have to move to some other
> state if the expected event not received in that time. All other
> events should be ignored in state "open".
> Problem: Below works fine if no events other than expected comes. But
> what happend if SOME un-expected events received before timeout? It
> always keep updating the timeout value to 5000. Removing the timeout
> value from {next_state, open, State,5000} for "OtherEvents" will cause
> to stuck in the "open" forever if the expected event not received.
> Question: How the time out value should be use in this case ? Are
> there any way to set the timeout value ONCE for all "OtherEvents".
> -------------------------------------------
> Asume this as beginning point 
>    as(blah,blah), %%Calling Async Func
> {next_state, open, State,5000}; 
> -------------------------------------------
> open(timeout, State) ->
>     do_something,
>     {next_state, Any_Appropriat, State}.
> open(as_E, State) ->
>     do_something,
>     {next_state, Any_Appropriat, State}.
> open(OtherEvents, State) ->
>      {next_state, open, State,5000}.
> Thanks in advance
> Sanjaya Vitharana
> _______________________________________________
> erlang-questions mailing list
> http://www.erlang.org/mailman/listinfo/erlang-questions
Matthew Reilly

Gizmo Project name: matt 

More information about the erlang-questions mailing list