package nachos.threads; import nachos.machine.*; /** * A <i>communicator</i> allows threads to synchronously exchange 32-bit * messages. Multiple threads can be waiting to <i>speak</i>, * and multiple threads can be waiting to <i>listen</i>. But there should never * be a time when both a speaker and a listener are waiting, because the two * threads can be paired off at this point. */ public class Communicator { /** * Allocate a new communicator. */ public Communicator() { this.listenerQueue = ThreadedKernel.scheduler.newThreadQueue(true); this.speakerQueue = ThreadedKernel.scheduler.newThreadQueue(true); } /** * Wait for a thread to listen through this communicator, and then transfer * <i>word</i> to the listener. * * <p> * Does not return until this thread is paired up with a listening thread. * Exactly one listener should receive <i>word</i>. * * @param word the integer to transfer. */ public void speak(int word) { //Disable interrupts boolean intStatus = Machine.interrupt().disable(); KThread thread = null; //While there is no listener in the listener queue while((thread = listenerQueue.nextThread()) == null){ //Puts speaker in the speaker queue this.speakerQueue.waitForAccess(KThread.currentThread()); //Puts speaker to sleep KThread.sleep(); } buffer = word; //Wakes up the listener thread.ready(); //Restores interrupts Machine.interrupt().restore(intStatus); } /** * Wait for a thread to speak through this communicator, and then return * the <i>word</i> that thread passed to <tt>speak()</tt>. * * @return the integer transferred. */ public int listen() { //Disable interrupts boolean intStatus = Machine.interrupt().disable(); KThread thread = null; //Gets the first speaker in the speaker queue thread = speakerQueue.nextThread(); //Puts the listener in the listener queue this.listenerQueue.waitForAccess(KThread.currentThread()); //If there is a speaker if(thread != null){ //Wake up that speaker thread.ready(); } //Puts the listener to sleep KThread.sleep(); //Restores interrupts and returns the buffer (word) Machine.interrupt().restore(intStatus); return buffer; } /** * Tests whether this module is working. */ public static void selfTest() { CommunicatorTest.runTest(); } private ThreadQueue listenerQueue; private ThreadQueue speakerQueue; private int buffer; }