-module(turnstile).
-export([start/0]).
-export([coin/0, pass/0]).
-export([init/0]).
start() -> register(turnstile, spawn(?MODULE, init, [])).
% Initial state
init() -> locked().
% Events
coin() -> turnstile ! coin.
pass() -> turnstile ! pass.
% States and transitions
locked() ->
receive
pass ->
alarm(),
locked();
coin ->
unlock(),
unlocked()
end.
unlocked() ->
receive
pass ->
lock(),
locked();
coin ->
thankyou(),
unlocked()
end.
% Actions
alarm() -> io:format("You shall not pass!~n").
unlock() -> io:format("Unlocking...~n").
lock() -> io:format("Locking...~n").
thankyou() -> io:format("Thank you for donation~n").
The idea behind this code is simple. Every state is implemented as a function that does two things: it listens for messages sent by other processes; when message is received the appropriate action is taken and one of the state-functions called recursively. Simple, right? And thread-safe!
3 comments:
Watch Rich Hickey's presentation. Erlang's way of state management seems to be right.
Thread-safe but not deadlock-safe :-) Even Erlang is not perfect. Actually, that's why it has OTP.
- Eugene Ossintsev
True, deadlocks are possible, but race condition is not, and this is already big advantage.
Post a Comment