Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

You have been hired by the CS Department to write code to help synchronize a pro

ID: 3540453 • Letter: Y

Question

You have been hired by the CS Department to write code to help synchronize a professor and his/her students during office hours. The professor, of course, wants to take a nap if no students are around to ask questions; if there are students who want to ask questions, they must synchronize with each other and with the professor so that

-       only one person is speaking at any one time,

-       each student question is answered by the professor, and

-       no student asks another question before the professor is done answering the previous one.

You are to write four procedures: AnswerStart(), AnswerDone(), QuestionStart() and QuestionDone().

The professor loops running the code: AnswerStart(); give answer; AnswerDone(). AnswerStart doesn%u2019t return until a question has been asked. Each student loops running the code: QuestionStart(); ask question; QuestionDone(). QuestionStart() does not return until it is the student%u2019s turn to ask a question. Since professors consider it rude for a student not to wait for an answer, QuestionEnd() should not return until the professor has finished answering the question. You can use a command line interface for this program. You are free to make other design choices and be creative in your implementation. You may use any programming language of your choice.

Explanation / Answer

/**

* You have been hired by the CS Department to write code to help synchronize a professor and his/her

* students during office hours. The professor, of course, wants to take a nap if no students are around

* to ask questions; if there are students who want to ask questions, they must synchronize with each

* other and with the professor so that (i) only one person is speaking at any one time, (ii) each student

* question is answered by the professor, and (iii) no student asks another question before the professor

* is done answering the previous one. You are to write four procedures: AnswerStart(), AnswerDone(),

* QuestionStart(), and QuestionDone(). Each function should print a message, indicating the action

* taken and the identity of the student involved.

* The professor loops running the code: AnswerStart(); give answer; AnswerDone(). AnswerStart doesn't

* return until a question has been asked. Each student loops running the code: QuestionStart(); ask

* question; QuestionDone(). QuestionStart() does not return until it is the student's turn to ask a

* question. Since professors consider it rude for a student not to wait for an answer, QuestionEnd()

* should not return until the professor has finished answering the question.

* Make sure your solution can be run using the command line "nachos -prof <numStudents>".

*/

public class ProfessorStudent implements Runnable {

  

// number of students

private int numStudents = -1;

  

// number of questions allowed per student

private int numberOfQuestionsAllowed;

  

// number of students waiting for the prof

private static int waitingStudents = 0;

  

// used by the professor to wait for students to ask a question

// it is a condition since signaling without anybody waiting should be

// ignored. semaphores 'remember' signals.

// the professor will wait if waitingStudents is 0, if somehow a student

// reaches the signal call before the professor, it means (we force the students

// to increment waitingStudents after acquiring a lock) that the student increment

// the waitingStudents variable, thus, the professor will not 'wait' (take a nap)

private static Condition professor = new Condition("Professor");

  

// the student and the professor use these two conditions to communicate

// we thought of semaphores, since the students might 'signal' the professor before

// the professor is ready... in this way, it is irrelevant whether the students

// wait for the professor to arrive (Professor thread to be created), or the

// professor sleeps while waits for the students to arrive (Student threads to

// be created)

private static Semaphore professorToken = new Semaphore("ProfessorToken", 0);

private static Semaphore studentToken = new Semaphore("StudentToken", 0);

  

// lock to modify shared variables

private static Lock sharedVariables = new Lock("SharedVariables");

  

// once a student gets into the office, he "locks" it, so no other student

// gets into it to ask questions, other students trying to get the professor

// will block here

private static Lock office = new Lock("Office");

  

public ProfessorStudent(int numStudents, int numberOfQuestionsAllowed) {

Debug.ASSERT(numStudents >= 0, "Number of students cannot be negative!");

this.numStudents = numStudents;

this.numberOfQuestionsAllowed = numberOfQuestionsAllowed;

}

  

/**

* This method will create as many students threads as needed and one professor thread.

*/

public void run() {

Debug.printf('+', "Starting Professor with %d students ", new Long(numStudents));

Debug.printf('+', "Each student is allowed to ask [%d] questions (-1 == infinite) ", new Long(numberOfQuestionsAllowed));

  

// first, create the professor thread

NachosThread professorThread = new NachosThread("Professor");

professorThread.fork(new Professor());

  

// now, the students

for (int i = 0; i < numStudents; i++) {

NachosThread studentThread = new NachosThread("Student #" + i);

studentThread.fork(new Student(numberOfQuestionsAllowed));

  

} // for

  

} // run

  

/**

* From an array of Objects, it will return a random element.

*

* @param array The array of objects.

*

* @return The random element.

*/

private Object getRandomElement(Object[] array) {

return array[(int)(Math.random() * (array.length - 1))];

  

} // getRandomElement

  

/**

* AnswerStart doesn't return until a question has been asked.

*/

private void AnswerStart() {

Debug.println('+', "[AnswerStart] BEGIN");

// modify shared variables, getting the lock first

sharedVariables.acquire();

  

// if there's no one at the door, sleep

while (waitingStudents == 0) {

Debug.println('+', "[AnswerStart] Professor says: No students. NAP TIME!");

Debug.println('e', "[AnswerStart] (Professor) professor.wait()");

professor.wait(sharedVariables);

}

  

waitingStudents--;

sharedVariables.release();

  

// we were either waken up from our nap or there were students waiting already

// if there's a student already in the office, wait for him to leave

Debug.println('+', "[AnswerStart] Professor says: Next please!");

Debug.println('e', "[AnswerStart] (Professor) professorToken.P()");

professorToken.P();

  

// signal the student to come in

Debug.println('e', "[AnswerStart] (Professor) studentToken.V()");

studentToken.V();

  

Debug.println('+', "[AnswerStart] Professor says: Come in please.");

  

// and now, wait for a question to be asked

Debug.println('e', "[AnswerStart] (Professor) professorToken.P()");

professorToken.P();

  

Debug.println('+', "[AnswerStart] END");

  

} // AnswerStart

  

private void GiveAnswer() {

Debug.println('+', "[GiveAnswer] BEGIN");

Debug.println('+', "[GiveAnswer] Professor says: Interesting question... Let me think.");


String answers[] =

{

"42", "I'm not sure.", "Definitively.", "I do not understand your question.",

"Please, come back on Monday.", "Sorry, I'm retiring tomorrow.",

"You need to restate your question.", "If I knew I would tell you.",

"PI divided by 4.", "0,87 radians.", "That was not a question, try again!"

};

  

// generate the answer

String answer = (String)getRandomElement(answers);

Debug.printf('+', "[GiveAnswer] Professor answers: %s ", answer);

Debug.println('+', "[GiveAnswer] END");

  

} // GiveAnswer

  

private void AnswerDone() {

Debug.println('+', "[AnswerDone] BEGIN");

// signal the student that the answer is done

Debug.println('+', "[AnswerDone] Professor says: I hope that helped.");

Debug.println('e', "[AnswerDone] (Professor) studentToken.V()");

studentToken.V();

  

// and wait for him to leave

Debug.println('+', "[AnswerDone] Professor waits for student to leave the office.");

Debug.println('e', "[AnswerDone] (Professor) professorToken.P()");

professorToken.P();

  

Debug.println('+', "[AnswerDone] END");

  

} // AnswerDone

  

/**

* QuestionStart() does not return until it is the student's turn to ask a question

*/

private void QuestionStart() {

Debug.printf('+', "[QuestionStart] (%s) BEGIN ", NachosThread.currentThread().getName());

  

// assume we will wait

sharedVariables.acquire();

waitingStudents++;

sharedVariables.release();


// ok, so lock the office

Debug.printf('e', "[QuestionStart] (%s) office.acquire() ", NachosThread.currentThread().getName());

office.acquire();


// let know the prof we are here

Debug.printf('e', "[QuestionStart] (%s) professor.signal() ", NachosThread.currentThread().getName());

professor.signal(office);

  

Debug.printf('+', "[QuestionStart] %s is thinking of a question ", NachosThread.currentThread().getName());

Debug.printf('+', "[QuestionStart] %s is waiting for the prof to open the door ", NachosThread.currentThread().getName());

Debug.printf('e', "[QuestionStart] (%s) professorToken.V() ", NachosThread.currentThread().getName());

professorToken.V();

  

// if the prof was with another student

  

// and wait the prof to listen

Debug.printf('e', "[QuestionStart] (%s) studentToken.P() ", NachosThread.currentThread().getName());

studentToken.P();

Debug.printf('+', "[QuestionStart] %s says: "Hello Prof!" and gets into the office ", NachosThread.currentThread().getName());

  

Debug.printf('+', "[QuestionStart] (%s) END ", NachosThread.currentThread().getName());

  

} // QuestionStart

  

private void AskQuestion() {

Debug.printf('+', "[AskQuestion] (%s) BEGIN ", NachosThread.currentThread().getName());

  

String questions[] =

{

"What is the 1001th prime number?", "What is the last digit of PI?", "What is the answer for all questions?",

"How can one compute the real component of the square root of -1?", "Why do we use greek letters instead of latin ones?",

"What is the sound of one hand?", "Why is the sky blue?", "Why do we always see the same side of the moon?",

"What's on the deep end of the pool?", "Do babies really come from Paris?"

};


// generate question

String question = (String)getRandomElement(questions);

Debug.printf('+', "[AskQuestion] %s asks: %s ", NachosThread.currentThread().getName(), question);


  

// signal the professor

Debug.printf('e', "[AskQuestion] (%s) professorToken.V() ", NachosThread.currentThread().getName());

professorToken.V();

  

Debug.printf('+', "[AskQuestion] (%s) END ", NachosThread.currentThread().getName());

  

} // AskQuestion

  

/**

* QuestionEnd() should not return until the professor has finished answering the question.

*/

private void QuestionDone() {

Debug.printf('+', "[QuestionDone] (%s) BEGIN ", NachosThread.currentThread().getName());

  

// we must wait for the prof to be done

Debug.printf('+', "[QuestionDone] %s is waiting for an answer. ", NachosThread.currentThread().getName());

Debug.printf('e', "[QuestionDone] (%s) studentToken.P() ", NachosThread.currentThread().getName());

studentToken.P();

  

// the professor answered

Debug.printf('+', "[QuestionDone] %s says: Thanks for the answer! ", NachosThread.thisThread().getName());

  

// leave

Debug.printf('e', "[QuestionDone] (%s) professorToken.V() ", NachosThread.currentThread().getName());

professorToken.V();

  

// we're done, so just leave

Debug.printf('e', "[QuestionDone] (%s) office.release() ", NachosThread.currentThread().getName());

office.release();

  

Debug.printf('+', "[QuestionDone] %s leaves the office. ", NachosThread.currentThread().getName());

Debug.printf('+', "[QuestionDone] (%s) END ", NachosThread.currentThread().getName());

  

} // QuestionDone

  

private class Professor implements Runnable {

/**

* Implements the professor cycle

*/

public void run() {

while(true) {

AnswerStart();

GiveAnswer();

AnswerDone();

}

} // run

  

} // class

  

private class Student implements Runnable {

// each student is allowed to ask this many questions, -1 if infinite

private int numberOfQuestionsAllowed = -1;

  

/**

* Constructor.

*

* @param numberOfQuestionsAllowed How many questions is this student allowed to ask

*/

public Student(int numberOfQuestionsAllowed) {

this.numberOfQuestionsAllowed = numberOfQuestionsAllowed;

  

} // ctor

  

/**

* Implements the student cycle

*/

public void run() {

while(true) {

if (numberOfQuestionsAllowed > 0) {

numberOfQuestionsAllowed--;

} else if (numberOfQuestionsAllowed == 0) {

return;

}

QuestionStart();

AskQuestion();

QuestionDone();

NachosThread.thisThread().Yield();

}

}

  

} // class


} // class

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote