The general idea of this simulation is to simulate a very successful borscht restaurant. Borscht is versatile, tasty, and generally very popular. There will be three main roles that a thread can play in the simulation:
- Customer, who arrive at the restaurant, wait to be seated, order, eat, then leave.
- Wait staff, who wait for customers, seat those customers in their assigned sections, and serve customers food
- Cooks, who receive orders, prepare bowls of borscht and give them to the wait staff
Each thread has a set of valid interactions with other threads. These interactions are affected by the global state of the restaurant.
The specifics of how a thread may manipulate the state of the restaurant is located in the function comments in sim.h.
The behavior of a customer is as follows:
-
When they arrive they need to be seated. See the wait staff thread information for this API call.
-
Like all restaurants, there is a queue and (barring some absurd social behaviors) the customer at the front of the queue is always seated first. The current state of the queue at the restaurant is accessible through the API via
get_waiting_line(customer_id**, size_t*). -
Once a customer is seated, they would like to have some number of bowls of borscht,
$n$ , of some preparation type,$t$ .- However, being easily embarrassed, customers would only like to have a single bowl of borscht at their table at any given time.
- That is, a customer must finish eating the current bowl of borscht before a member of the wait staff brings another bowl (if needed).
- A customer thread can eat via
eat(customer_id). - A customer must eat
$n$ bowls of borscht before leaving.
-
Once they have eaten their fill, they leave, making sure to tip the waitstaff before they go (borscht is otherwise provided free of charge to the community).
- A customer thread can leave via
leave(customer_id).
- A customer thread can leave via
Each member of the wait staff has a section of seats in the restaurant for which they are responsible.
For example, if the set of seats in the restaurant is
Waitstaff actions are much different than the customer actions in that they can be in any order as long as no action violates the state of the restaurant.
The possible actions of the wait staff are as follows:
-
They can seat a customer via
seat(waitstaff_id, customer_id, table_id)- A member of the wait staff can only seat a customer in their section.
- They must seat the customer at the front of the queue
- They cannot seat a customer at a dirty table.
- They cannot seat a customer at a table which is already occupied
- Hint: Everyone on the wait staff is a team player, and knows that service is much more efficient if the workload is evenly distributed.
-
Being very in touch with their customer base (and the community at large), they can intuit a customers borscht preference via
intuit_preference(customer_id)- Note that this customer need not be in any particular state other than arrived at the restaurant.
-
They can take a customers order via
take_order(waitstaff_id, customer_id, int)- Although they know what type of borscht a customer likes, the waitstaff is not so experienced that they can intuit how hungry a customer is
- In order for a customer's order to be taken they must
- Be seated in this waitstaff's section
- Not have already ordered
-
They can pick up borscht from the kitchen via
pick_up_borsht(waitstaff_id, borscht_type, int)- This call will result in an invalid state if the kitchen does not have the requested quantity of the specified borscht type available.
-
They can serve borscht to a customer via
serve(waitstaff_id, table_id, borscht_type)- This customer must
- Not be eating
- Have ordered
- Be seated in this wait staff member's section
- Not yet have eaten their desired quantity of borscht
- The member of the wait staff must be carrying at least one bowl of the specified borscht type. See
pick_up_borsht(waitstaff_id, borscht_type, int)
- This customer must
-
They can clean a table via
clean_table(waitstaff_id, table_id)- This table must:
- Not be occupied
- This table must:
Note that members of the wait staff must inform the kitchen of the customer preference and desired quantity in some way, However,
- There are no API calls for this.
- A data structure to track orders must be created
- Note: A cook thread's call to
prepare(borscht_type, int)must not exceed the ordered amount of borscht at that time. See the Cook thread description for more detailed information.
Each member of the kitchen is responsible for preparing borscht.
The members of this kitchen are very organized and after many years of preparing borscht, have determined that there are generally a few distinct ways to prepare a bowl, this is the borscht_type seen throughout the API. The number of types of borscht can be obtained via types_of_borsht()
The behavior of the cooks is as follows:
- Cooks receive orders from wait staff through some data structure, prepare some number of bowls borscht, then inform the appropriate member of the wait staff once the order is "up".
- A cook may prepare multiple bowls of borscht at time, but only if they are of the same type
- For example, a cook may
prepare(1, 3)for preparing3bowls of type1orprepare(1)for just a single bowl of type1. - Note that it is much more efficient to prepare bowls of
borschtin batches!
This API call will fail if the total number of bowls prepared of some specified type after this call will exceed the total number of bowls of that type ordered.
This rule is to prevent front loading of the call! Being able to prepare, say, 10,000 bowls of each type right when the restaurant opens would sure make that prepare call efficient, but, might result in (unforgivable) w@st#d borscht!
Consider the small sequence of actions for clarification on when this call may fail:
- The restaurant has 1 customer,
customer1, and one waiterwaitstaff1. waitstaff1seatscustomer1then seatscustomer2- A call to
preparewith aquantityargument greater than 0 will fail waitstaff1takes the order ofcustomer1, they want2bowls of type1.- A call to
preparewith aquantityof2and type1will not fail - A subsequent call to
preparewith aquantityof2and type1will fail - A call to
preparewith aquantitygreater than zero and any type other than1will fail