Recharging Robots
(aka The Sleepy Barber Problem)
We first examine a trivial solution that simplifies the problem
by only considering one type of process: that of the customer.
All actions performed by the barber are conveniently ignored.
(This solution is therefore insufficient, as it ignores some
of the rules, but it serves as a good
starting point.) To avoid worrying about race conditions on
shared variables, we do all of the work within the monitor.
monitor barberShop {
int numWaiting = 0; // nobody in chairs
boolean sleeping = TRUE; // the barber is sleeping
condition chair; // someone is waiting in a chair
enter() {
if (numWaiting == NUM_CHAIRS)
exit();
else if (sleeping == TRUE)
sleeping = FALSE;
else {
numWaiting++;
chair.wait(); // don't hog monitor while we wait
numWaiting--;
sleeping = FALSE;
}
}
leave() {
sleeping = TRUE;
if (chair.queue()) // someone is sitting in a chair
chair.signal(); // tell first person barber is free
}
}
customer () {
barberShop.enter();
< get haircut >
barberShop.leave();
}
Based on this exercise, we can now try a full solution that also deals
with the rules incumbent upon the barber process. To expose all the
details, we will break away from the monitor and use condition
variables (Brinch Hansen semantics) for all steps of synchronization.
While this solution is more detailed, it suffers from a potential
fairness problem that was raised in class... can you find it?
int waiting = 0; // # custs waiting
boolean sleeping = FALSE; // barber is awake
condition door; // mutual exclusion
condition barber; // customer-barber synch
condition seats; // customers waiting
Customer() {
door.wait(); // only one at a time
if (waiting == NUM_CHAIRS) { // this place is full
door.signal(); // let others proceed
exit(); // but I'm out of here
}
else if (sleeping) { // barber is not busy
barber.signal(); // synch with barber (wake him)
door.signal(); // let others come in
< get haircut >
barber.signal(); // synch with barber ("thanks")
}
else { // barber is busy
waiting++; // take a chair
door.signal(); // let others come in
seats.wait(); // now wait my turn
waiting--; // get out of chair
< get haircut >
barber.signal(); // synch with barber ("thanks")
}
}
Barber() {
door.signal(); // in case we start after
// first customer has arrived
while (1) {
door.wait(); // mutex to check for waiting
if (waiting == 0) { // nobody waiting, go to sleep
sleeping = TRUE;
door.signal(); // release mutex
barber.wait(); // wait to be awoken
sleeping = FALSE;
}
else {
seats.signal(); // ready for next customer
door.signal(); // release mutex
}
barber.wait(); // synch ("you're welcome")
}
}