[erlang-questions] gen_statem: Join states?

Jesper Louis Andersen jesper.louis.andersen@REDACTED
Sat Jun 23 12:21:36 CEST 2018

I usually stuff the events into a map and then have a handle_continue/2
like behavior to check if everything in the map is present.


event(a, State) ->
    check(State#{ a => true });
event(b, State) ->
    check(State#{ b => true });

check(#{ a := A, b := B} = State) ->
    end(A, B, State);
check(#{} = State) ->
    {noreply, ...}.

Usually, rather than storing true, I'd store the event data there, and
rather than having a map() at the top-level I'd probably have a record. But
the gist of the idea is there. A more advanced variant of this will have a
defined state machine and valid transitions between them. Then check is
also an invariant on the transitions validity and it becomes a (runtime)
contract to check against.

Aside: Idris can do this check at compile time, but since we don't have
dependent types...

On Sat, Jun 23, 2018 at 9:07 AM Oliver Korpilla <Oliver.Korpilla@REDACTED>

> Hello.
> In the system we're building we're using gen_statem processes to keep
> track of signalling scenarios, essentially series of different types of
> messages from various sources. For linear or branching scenarios gen_statem
> is well prepared. But there's one thing that seemed to be missing and that
> is support for joins?
> I recently reviewed a developer's code that implemented receiving two
> different messages that could arrive in any order as four state functions -
> receiving A first (1), then receiving B (2), then entering an end state; or
> receiving B first (3), then receiving A (4), then entering an end state.
> The code entering the end state was duplicated in both (2) and (4). What
> essentially was needed was a "check list" of which messages had already
> arrived to determine the transition into the end state.
> Such "check list" scenarios are quite common in our work (and can grow to
> be more complex) and I couldn't find a direct support for it (though I was
> limiting myself to state_function mode), so we're now starting a separate
> "join process" - a gen_server that keeps and maintain the join list - and
> do the decision now from a single wait state. Given how light-weight Erlang
> processes are this works fine.
> What prevented me from doing this through data maintained between calls
> was that I would have to partition the state into information for tracking
> the join and the actual information kept to process the signals. This
> seemed less generic and clean.
> I'm also aware that had I rewritten the whole state machine to
> handle_event functions and utilized a complex state this could have helped
> achieve the same. What is essentially is needed, from my POV, is a way to
> track information pertaining to state transitions separate from information
> for processing incoming events, and complex states seem to do that...?
> What is your preferred way of doing this? Is it possible to somehow
> support this at the library level? Are handle_event/complex states the way
> to go in such situations?
> Thank you and regards,
> Oliver
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20180623/6aea1f35/attachment.htm>

More information about the erlang-questions mailing list