[erlang-questions] Implementing a loop that quits on an external event.

Iñaki Garay igarai@REDACTED
Fri Dec 16 23:40:00 CET 2011


Hello everyone,

Short story:
how could I implement a loop that can quit on an external event using
the OTP behaviours?
One option I can think of is a gen_fsm that has a transition to the
current state, and sends itself a message at the end of the
transition.
Another is having two processes, one watching for the external event
or message, and when it occurs sets some sort of shared variable, e.g.
in an ETS table, while another executes the loop and checks whether
the shared variable was set to 'quit'.
Any other options?
Problems with these?
Existing examples of this situation?
how is this usually done?

Long story:
You have a dream^W game, a small multi-agent simulator.
You have an environment, which is the state of the world.
Agents are gen_servers, you give them a percept and ask for an action.
Actions modify the world.
During  one iteration of the simulation loop, it tells each agent what
it perceives and asks what action it will perform, and then applies
the action's effects on the environment state.

The environment simulator is a gen_fsm.
It has (among others), two states: paused, and running.

When paused, if it receives a 'run' message, it transitions to the
running state.
If it receives a 'quit' message, it stops.

When running, if it receives a 'pause' message, it switches to the paused state.
Also when running, it "runs the simulation".

Now, the 'running' state shouldn't have to wait each iteration for
input to continue on to the next simulation iteration.
I can think of two ways to do this:

1. An 'epsilon transition', that is, a transition that fires without
input to the FSM.
The simulator gen_fsm could send_event 'run' to itself, at the end of
each iteration.
Every time it receives a 'run' message, one iteration of the
simulation cycle is executed.

2. Outsource the main loop to another process.
The gen_fsm in the running state now waits for the 'pause' message,
and when received, signals the other process running the tight loop.
The 'signal' could be a message: the looping process has a receive
with a timeout of 0, every time it checks if there is no message it
continues the cycle.
Or it could be some shared state, e.g. something in an ETS table,

In the first case, I can imagine the gen_fsm executing an iteration,
and simulatenously the pause event is received.
At the end, it sends itself the 'run' message, and transitions to the
'paused' state.
A spurious message is left in the queue, possibly messing things up later on.
Also, waiting for a message, even one you "just sent", may possibly
take longer than expected than just comparing a value, or even
executing a receive statement with a timeout of 0.

In the second case, shared state, and a more complicated design.

Am I overthinking?

many thanks in advanced,
Iñaki Garay.



More information about the erlang-questions mailing list