package nachos.threads;
import nachos.machine.*;
import java.util.Queue;
/**
* 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() {
inTransaction = false;
}
/**
* 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) {
commLock.acquire();
while(inTransaction || listenerQueue.getThreadCount() == 0) {
//System.out.println("speaker " + KThread.currentThread() + " sleep, " + speakerQueue.getThreadCount() + " speakers " + listenerQueue.getThreadCount() + " listeners");
speakerQueue.sleep();
//System.out.println("speaker " + KThread.currentThread() + " wake, " + speakerQueue.getThreadCount() + " speakers " + listenerQueue.getThreadCount() + " listeners");
}
inTransaction = true;
msg = word;
listenerQueue.wake();
commLock.release();
//System.out.println("speaker " + KThread.currentThread() + " out, " + speakerQueue.getThreadCount() + " speakers " + listenerQueue.getThreadCount() + " listeners");
}
/**
* 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() {
int ret;
commLock.acquire();
while(!inTransaction) {
if(speakerQueue.getThreadCount() > 0)
speakerQueue.wake();
//System.out.println("listener " + KThread.currentThread() + " sleep, " + speakerQueue.getThreadCount() + " speakers " + listenerQueue.getThreadCount() + " listeners");
listenerQueue.sleep();
//System.out.println("listener " + KThread.currentThread() + " wake, " + speakerQueue.getThreadCount() + " speakers " + listenerQueue.getThreadCount() + " listeners");
}
ret = msg;
inTransaction = false;
if(listenerQueue.getThreadCount() > 0 && speakerQueue.getThreadCount() > 0)
speakerQueue.wake();
commLock.release();
//System.out.println("listener " + KThread.currentThread() + " out, " + speakerQueue.getThreadCount() + " speakers " + listenerQueue.getThreadCount() + " listeners");
return ret;
}
private Lock commLock = new Lock();
private Condition2 speakerQueue = new Condition2(commLock);
private Condition2 listenerQueue = new Condition2(commLock);
private int msg;
private boolean inTransaction;
}