After working on Sleeping Barber problem at Coding Dojo I decided to implement it in Erlang. Because Erlang is the perfect language for these sorts of problems, many people have alredy solved it in many different ways. I found at least three groups of solutions: 1) direct implementation using message passing between processes, 2) OTP solution using gen_server, and 3) something resembling object-oriented approach.
Strangely enough, I didn’t see any solution based on FSM. That is odd because this is the first thing coming to my mind when I hear this problem. To fill the gap, I’m going to solve it using gen_fsm, which is a standard OTP behaviour for FSM.
Overview of gen_fsm
In essence gen_fsm behaviour is built the same way as a naïve implementation of FSM. It just hides the low-level code that deals with messages and provides integration with OTP framework. An implementation of gen_fsm behaviour consists of three parts
A client API that calls gen_fsm public interface
gen_fsm callbacks required by OTP
State transition functions
We’ll see examples of all of them in a minute, but first
Barber shop. The Barber is sleeping in the chair. Customer I comes in.
Customer I. Good morning. Barber. Good morning. Please take a seat.
Barber starts shaving Customer I. Customer II comes in.
Customer II. Good morning. Barber. I’m busy. You have to wait. Customer II. OK.
Customer II goes to waiting room. The same happens with Customers III and IV. Customer V comes in.
Customer V. Good morning. Barber. Sorry Customer V. Not today. Customer V. Maybe tomorrow.
Customer V exits the shop. Meantime Barber finished Customer I’s haircut.
Barber. Do you like your haircut? Customer I. Thank you. Barber (looking at Customer II). Next please.
The same happens with Customer II, III and IV. After that Barber takes the chair and sleeps.
From this dialogue we can see we just need to implement two modules: barber and customer.
I’m not going to show all the functions here in this article, only those that are interesting from gen_fsm perspective.
Let’s start with customer because it’s simpler.
barber module is little bit more complicated, because it not only calls customer’s API, it also sends events to itself.
To reproduce the dialogue above we evaluate the following expressions in the REPL