p1/threads/Communicator.java

90 lines
2.1 KiB
Java

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()
{
}
/**
* 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)
{
condLock.acquire();
if(protect==1) condProtect.sleep();
speakers++;
protect=1;
if(listeners==0)
{
condSpeaker.sleep();
message=word;
condPaired.wake();
}
else
{
message=word;
listeners--;
speakers--;
condListener.wake();
}
condLock.release();
}
/**
* 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=0;
condLock.acquire();
listeners++;
if(speakers==0) condListener.sleep();
else
{
speakers--;
listeners--;
condSpeaker.wake();
condPaired.sleep();
}
ret=message;
protect=0;
condProtect.wake();
condLock.release();
return ret;
}
private int speakers=0;
private int listeners=0;
private int protect=0;
private int message=0;
private Lock condLock=new Lock();
private Condition condProtect=new Condition(condLock);
private Condition condSpeaker=new Condition(condLock);
private Condition condListener=new Condition(condLock);
private Condition condPaired=new Condition(condLock);
}