Con­sid­er­ing a very sim­ple finite state machine (FSM) such as a code lock which requires you to enter a 4-digit numeric code and upon which will open the lock for a brief few seconds.

imageSuch a FSM have two states: Locked and Open.

Every time a key is entered it checks the sequence of dig­its inputted so far and if the sequence does not match the secret code then it stays in the Locked state.

If the input sequence matches the length of the secret code then the user is judged to have entered an incor­rect sequence and the input sequence is reset.

If, on the other hand, the user has entered the cor­rect code then the FSM will change to the Open state for a num­ber of sec­onds before revert­ing back to the Locked state.

This post is intended to show you how you can imple­ment this FSM eas­ily using F#’s agent and Erlang OTP’s gen_fsm behaviour.

 

 

 

F#

First, let’s define the dif­fer­ent states that our FSM can be in:

image

and then the mes­sages that our agent can receive:

image

The actual FSM imple­men­ta­tion looks like this:

This imple­men­ta­tion is pretty straight for­ward, I’ve used a sim­i­lar tech­nique to the one Tomas Pet­ricek used in his Block­ingQueueAgent imple­men­ta­tion and rep­re­sented the dif­fer­ent states using recur­sive functions.

One caveat with this FSM is the need to revert back to the Locked state after being in the Open state for a cer­tain amount of time. For sim­plic­ity sake, I’ve sim­ply spec­i­fied a time­out (3 sec­onds) when wait­ing for mes­sages in the Open state and use the Time­ou­tEx­cep­tion as cue to go back to the Locked state. The obvi­ous down­side to my imple­men­ta­tion here is that if a Get­State mes­sage is received it will reset the timer!

You can fix this eas­ily enough in a num­ber of ways, includ­ing using a muta­ble instance vari­able to keep track of the cur­rent state and let the async lamb­das mod­ify it dur­ing state changes and tran­si­tions, then the Get­State() method would no longer need to trou­ble the agent to find out what the cur­rent state is.

 

Erlang

Erlang’s OTP frame­work pro­vide a gen_fsm behav­iour which you can use to imple­ment a FSM, which will take care of most of the plumb­ing and orches­tra­tion for you leav­ing you free to focus on the impor­tant things – han­dling the dif­fer­ent ‘events’ that can be trig­gered dur­ing dif­fer­ent states.

This Erlang imple­men­ta­tion might look much big­ger than its F# coun­ter­part but keep in mind that I’ve included plenty of com­ments here and not been as con­ser­v­a­tive with write spaces as I was with the F# code. All and all, both ver­sions require roughly the same num­ber of LOC, the main dif­fer­ence being the lack of plumb­ing in the Erlang ver­sion, which if I have to be hon­est, can be con­fus­ing if you don’t have a decent under­stand­ing of how the gen_fsm behav­iour works!

You can down­load and play around with the full source code (with cor­re­spond­ing tests for each imple­men­ta­tion) from Github here. Enjoy!

Share

Leave a Reply