package EDU.cmu.softagents.util;
import java.util.*;
/** GenericQueue class: This class implements a queue. The class
is thread-safe and has wait-notify mechanism in it.
@version 06/30/97
@author Somesh Jha
*/
public class GenericQueue {
static final int MAX=500;
int front, back;
int size;
Object queue[];
public GenericQueue() {
size = MAX + 1; // + 1 so queue can actually hold MAX items
queue = new Object[size];
front=0;
back=0;
} // end of constructor
/** Arg, size, is the desired capacity of the queue. If size is
not positive, a defalut size is used.
*/
public GenericQueue(int size) {
// If size arg is invalid, set size to default.
if (size < 1) size = MAX;
// We must add 1 to size arg, else queue can hold only
// size-1 items and a size arg of 1 would produce an error.
this.size = size + 1;
queue = new Object[this.size];
front =0;
back=0;
} // end of constructor
/** Check whether queue is empty
*/
public boolean isEmpty() {
return (front == back);
}
/** Check whether queue is full
*/
public boolean isFull() {
return((back+1)%size == front);
}
/** Report number of elements the queue can hold.
*/
public int capacity() {return size-1;}
/** Report number of elements currently in queue.
*/
public int numberOfElements() {
if (front > back)
return size - (front - back);
else
return back - front;
}
/** Synchronized method adding an object.
Wait if the queue is full and notify if the queue
was empty.
**/
public synchronized void addObject(Object obj) {
while (isFull())
try {wait();}
catch (InterruptedException ex){};
queue[back]=obj;
boolean flag=isEmpty();
back = (back+1)%size;
//notify if the queue was empty
if (flag) notifyAll();
} // end of addObject
/** Synchronized method for deleting an object.
Wait if the queue is empty and notify if the queue
was full.
**/
// NOTE: This method could be subsumed by removeObject().
//
public synchronized void deleteObject() {
while (isEmpty())
try {wait();}
catch (InterruptedException ex){};
queue[front]=null;
boolean flag = isFull();
front = (front+1)%size;
//notify other threads if the queue was
// full
if (flag) notifyAll();
}
/** Get the front of the queue. Return null if
the queue is empty.
*/
// Synchronized to prevent subscript range error with front.
//
public synchronized Object getObject() {
if (isEmpty()) return(null);
else return(queue[front]);
}//end of getObject
/** Replace the front element of the queue. Return the old
front element or null if the queue was empty.
*/
public synchronized Object replaceObject(Object obj) {
if (isEmpty()) {
addObject(obj);
return null;
} else {
Object retval = queue[front];
queue[front] = obj;
return retval;
}
}
/** Synchronized method removes an Object from the queue.
Wait if the queue is empty and notify if the queue
was full.
**/
public synchronized Object removeObject() {
while (isEmpty())
try {wait();}
catch (InterruptedException ex){};
Object result=queue[front];
queue[front]=null;
boolean flag = isFull();
front = (front+1)%size;
//notify other threads if the queue was
// full
if (flag) notifyAll();
return(result);
}
/** Get enumeration type to go through the queue.
*/
public synchronized Enumeration elements() {
return(new QueueEnumeration(this));
} // end of elements
} // end of class GenericQueue
class QueueEnumeration implements Enumeration {
Object[] enumList = null;
int enumIndex = 0;
int enumSize = 0;
public QueueEnumeration(GenericQueue queue) {
// Build a private list of the queue's current members
// that we can then use to supply the enumeration.
enumSize = queue.numberOfElements();
enumList = new Object[enumSize];
int front = queue.front;
for (int i = 0; front != queue.back; i++) {
enumList[i] = queue.queue[front];
front = (front+1)%queue.size;
}
enumIndex = 0;
}
public boolean hasMoreElements() {
return (enumIndex < enumSize);
}
public Object nextElement() {
Object retval = null;
if (enumIndex < enumSize) {
retval = enumList[enumIndex];
enumIndex++;
}
return retval;
}
} // end of myEnumeration