1

I have a question on gen_fsm timeout. Let's say you have a set of gen_fsm with two states (in future can be more): idle which is the starting state and working.

Any 5 seconds the gen_fsm will check a particular parameter and according to it will remain in idle or will move to working. Whenever a gen_fsm will move to working, it will send a message (using gen_fsm:send_all_state_event/2) to all the other gen_fsm: the ones in idle should move to working while the one in working should not care about the incoming message.

Now, the point is that I don't want to have a skew in the states timeout (e.g. what happens if the machine is in working for 3 seconds and receives a message? A 5 seconds timeout is no more valid, since I want to preserve a fixed timeout no matter what (this means that a timeout message should be triggered at fixed times).

Here are the salient parts of my solution, which uses now() and time:now_diff/2. I have a small drift anyhow, but seems fair since talking about fractions of seconds.

Do you think it is valid?

{ok, idle, #state{time = now()}, 5000}.

idle(timeout, State) ->
    %% do some operations
    {next_state, idle, State#state{time = now()}, 5000}.

working(timeout, State) ->
    %% do some other actions
    {next_state, working, State#state{time = now()}, 5000}.

handle_event(work, working, #state{time = Time} = State) ->
    Timeout = round(timer:now_diff(now(), Time) / 1000),
    {next_state, working, State, Timeout}.

handle_event(work, StateName, state{time = Time} = State) ->
    Timeout = round(timer:now_diff(now(), Time) / 1000),
    {next_state, working, State, Timeout}.
user601836
  • 3,215
  • 4
  • 38
  • 48

1 Answers1

4

You can use either timer:apply_interval to call a api function that sends the event to your fsm.

Or you use timer:send_interval to send a custom message that you can handle in the handle_info callback in your gen_fsm.

Peer Stritzinger
  • 8,232
  • 2
  • 30
  • 43
  • In fact i changed the code using in each state gen_fsm:send_event_after(5000, timeout). what do you think of this? – user601836 Mar 05 '12 at 14:05
  • This has the disadvantages IMHO that you'll get some drifting of the interval again. To stay on a fixed interval you'll allways need to correct for the current time. The timer:*_interval functions do that correctly for free. – Peer Stritzinger Mar 06 '12 at 15:10