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")
	}
}