package nachos.threads;
import nachos.ag.BoatGrader;
public class Boat {
static BoatGrader bg;
static Communicator commFinish;
static Lock incrLock, boatLock, catmLock, cawcLock, wwLock;
static int adultsOahu, childrenOahu, adultsMolokai, childrenMolokai;
static boolean passengerTaken;
static Condition childrenAllToMolokai, comebackAndWakeCoordinator, waitWake;
public static void selfTest() {
BoatGrader b = new BoatGrader();
System.out.println("\n ***Testing Boats with only 2 children***");
begin(0, 2, b);
// System.out.println("\n ***Testing Boats with 2 children, 1 adult***");
// begin(1, 2, b);
// System.out.println("\n ***Testing Boats with 3 children, 3 adults***");
// begin(3, 3, b);
}
public static void begin( int adults, int children, BoatGrader b ) {
// Store the externally generated autograder in a class
// variable to be accessible by children.
bg = b;
// Instantiate global variables here
commFinish = new Communicator();
incrLock = new Lock();
boatLock = new Lock();
catmLock = new Lock();
childrenAllToMolokai = new Condition(catmLock);
cawcLock = new Lock();
comebackAndWakeCoordinator = new Condition(cawcLock);
wwLock = new Lock();
waitWake = new Condition(wwLock);
adultsOahu = 0;
adultsMolokai = 0;
childrenOahu = 0;
childrenMolokai = 0;
passengerTaken = false;
// Create threads here. See section 3.4 of the Nachos for Java
// Walkthrough linked from the projects page.
for(int i = 0; i < adults; i++) {
KThread t = new KThread(new Runnable() {
@Override
public void run() {
AdultItinerary();
}
});
t.setName("Adult #" + i);
t.fork();
}
for(int i = 0; i < children; i++) {
KThread t = new KThread(new Runnable() {
@Override
public void run() {
ChildItinerary();
}
});
t.setName("Child #" + i);
t.fork();
}
commFinish.listen();
bg.AllCrossed();
}
static void AdultItinerary() {
bg.initializeAdult(); //Required for autograder interface. Must be the first thing called.
//DO NOT PUT ANYTHING ABOVE THIS LINE.
/* This is where you should put your solutions. Make calls
to the BoatGrader to show that it is synchronized. For
example:
bg.AdultRowToMolokai();
indicates that an adult has rowed the boat across to Molokai
*/
incrLock.acquire();
adultsOahu++;
incrLock.release();
catmLock.acquire();
childrenAllToMolokai.sleep();
catmLock.release();
bg.AdultRowToMolokai();
adultsOahu--;
cawcLock.acquire();
comebackAndWakeCoordinator.wake();
cawcLock.release();
}
static void ChildItinerary() {
bg.initializeChild(); //Required for autograder interface. Must be the first thing called.
//DO NOT PUT ANYTHING ABOVE THIS LINE.
incrLock.acquire();
childrenOahu++;
incrLock.release();
ThreadedKernel.alarm.waitUntil(500);
while(true) {
boatLock.acquire();
if(!passengerTaken && childrenOahu > 0) {
passengerTaken = true;
bg.ChildRideToMolokai();
childrenOahu--;
childrenMolokai++;
boatLock.release();
while(true) {
cawcLock.acquire();
comebackAndWakeCoordinator.sleep();
cawcLock.release();
bg.ChildRowToOahu();
wwLock.acquire();
waitWake.wake();
wwLock.release();
bg.ChildRideToMolokai();
}
} else {
passengerTaken = false;
bg.ChildRowToMolokai();
childrenOahu--;
childrenMolokai++;
if(childrenOahu > 0) {
bg.ChildRowToOahu();
childrenMolokai--;
childrenOahu++;
boatLock.release();
} else {
// begin coordinating
bg.ChildRowToOahu();
childrenMolokai--;
childrenOahu++;
while(adultsOahu > 0) {
catmLock.acquire();
childrenAllToMolokai.wake();
catmLock.release();
wwLock.acquire();
waitWake.sleep();
wwLock.release();
bg.ChildRowToMolokai();
bg.ChildRowToOahu();
}
bg.ChildRowToMolokai();
childrenMolokai++;
childrenOahu--;
commFinish.speak(1);
return ;
}
}
}
}
}