You are asked to simulate a beer bar that has one bartender and many customers. You are asked to
synchronize the bartender and the customers. If there are customers who want to order the beer, they
must synchronize with each other and with the bartender so that (i) no more than a certain number of
customers can be in the bar at the same time because the bar has limited capacity, (ii) only one
customer can ask for beer at a time, (iii) each order can only be served by the bartender, (iv) no
customer asks for beer before the bartender is done serving the previous one, and (v) once a
customer finishes drinking enough cups of beers, he/she must leave the bar to make room for other
customers waiting outside.
You are to provide the following functions. In the next list, x is a placeholder for the customer
? Bartender(). This functions starts a thread that runs a loop calling ServeStart() and ServeDone().
See below for the specification of these two functions. ServeStart() blocks when there are no
customer in the bar.
? Customer(int id). This function creates a thread that represents a new customer with identifier
id that asks for one or more cups of beers (the identifier given to your function can be expected
to be greater or equal to zero and the first customer's id is zero). First, each customer needs to
enter the bar by calling EnterBar(). If the bar is already full, the customer must wait. After a
customer enters the bar, he/she loops running the code OrderStart(), OrderDone() and
DrinkBeer() for the number of cups of beer. The number of beer a customer needed is
determined by calculating (customer identifier modulo 3 plus 1). That is, each customer can ask
for between 1 and 3 cups, depending on the id. For example, a customer with id 2 needs 3 cups,
a customer with id 11 needs 3 cups and a customer with id 4 needs 2 cups. Once the customer
has had enough beer, he/she must call LeaveBar(). As a result, another customer waiting on
EnterBar() may be able to proceed.
? ServeStart(). The bartender starts to serve a cup of beer for a customer. Print “Bartender starts
to serve customer x”.
?ServeDone(). The bartender is done serving a cup for a customer. Print “Bartender is done with
serve customer x.”
? EnterBar(). It is the customer’s turn to enter the bar to drink. Print “Customer x enters the bar.”
? LeaveBar(). The customer had enough beer, so he/she leaves the bar. Print “Customer x leaves
? OrderStart(). It is the turn of the customer to ask his/her next beer. Print “Customer x asks for
beer.” Wait to print out the message until it is really that customer's turn.
? OrderDone(). The customer gets his/her beer. Print “Customer x gets the beer.” It should not
print anything until the Bartender has finished serving a request.
? DrinkBeer(). The customer drinks his/her beer. Print “Customer x drinks the beer.”
A customer can ask only one cup of beer each time. I.e., a customer only orders another cup after
he/she has finished the previous one.
Your program must accept one command line parameter that represents the number of customers
coming to the bartender’s bar, and a second command line parameter that represents the capacity of
the bartender’s bar (i.e., how many customers can be in the bar at the same time). For simplicity, you
can assume that the Customer threads are created at the ascending order of their identifiers. Your
program must validate the command line parameters to make sure that they are numbers, not arbitrary
Your program must be able to run properly with any reasonable number of customers (e.g., 100) and bar
capacity (e.g., 8)
Source code should include a Makefile.