Skip to content

Instantly share code, notes, and snippets.

@amclain
Last active July 1, 2020 22:29
Show Gist options
  • Save amclain/67b43f73e3b15cc86f957b3c1019ba19 to your computer and use it in GitHub Desktop.
Save amclain/67b43f73e3b15cc86f957b3c1019ba19 to your computer and use it in GitHub Desktop.
A simple Elixir experiment with the OTP state machine gen_statem
defmodule Turnstyle do
@moduledoc """
This state machine emulates a turnstyle gate that has a rotating bar
and a coin slot. If the gate is locked a coin must be inserted to unlock
it, and then the bar will rotate to let you through when it is pushed.
The bar will then lock back in position.
"""
@behaviour :gen_statem
def start_link do
:gen_statem.start_link(__MODULE__, nil, [])
end
def insert_coin(pid) do
:gen_statem.cast(pid, :insert_coin)
end
def push(pid) do
:gen_statem.cast(pid, :push)
end
# Callbacks
def callback_mode, do: [:state_functions, :state_enter]
def init(_) do
{:ok, :locked, nil}
end
def locked(:enter, _old_state, _data) do
IO.puts "Locked"
:keep_state_and_data
end
def locked(:cast, :insert_coin, data) do
IO.puts "Coin accepted"
{:next_state, :unlocked, data}
end
def locked(:cast, :push, _data) do
IO.puts "The bar doesn't move"
:keep_state_and_data
end
def unlocked(:enter, _old_state, _data) do
IO.puts "Unlocked"
{:keep_state_and_data, [{:state_timeout, 10000, :locked}]}
end
def unlocked(:state_timeout, :locked, data) do
IO.puts "Timed out - Your coin is returned"
{:next_state, :locked, data}
end
def unlocked(:cast, :insert_coin, _data) do
IO.puts "Your coin is returned"
:keep_state_and_data
end
def unlocked(:cast, :push, data) do
IO.puts "The bar rotates"
{:next_state, :locked, data}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment