package uk.co.mmscomputing.concurrent;
/*
Thread- und Netzwerk-Programmierung mit Java
ISBN 3-89864-133-3
p.67
*/
public class ArrayBlockingQueue extends Object{
protected Object[] buffer;
protected int size,front,rear;
protected boolean fcarry,rcarry;
protected Semaphore empty,full;
protected Object pt,gt;
public ArrayBlockingQueue(int init){
if(init<1){
throw new IllegalArgumentException(getClass().getName()
+".<init>(int init)\n\tParameter init must be greater than zero."
);
}
buffer=new Object[init];
size=init;
front=0;rear=0;
fcarry=false;rcarry=false;
empty=new Semaphore(init,true);
full=new Semaphore(0,true);
pt=new Object();
gt=new Object();
}
public boolean isEmpty(){
return(front==rear)&&(fcarry==rcarry);
}
public boolean isFull(){
return(front==rear)&&(fcarry!=rcarry);
}
synchronized public int size(){
int f=front,r=rear;
if((fcarry!=rcarry)||(r<f)){r+=size;}
return(r-f);
}
public int remainingCapacity(){
return size-size();
}
protected void add(Object v){
buffer[rear]=v;
rear++;if(rear>=size){rear-=size;rcarry=!rcarry;}
}
public void put(Object v)throws InterruptedException{
empty.acquire();
synchronized(pt){add(v);}
full.release();
}
public boolean offer(Object v){
try{
return offer(v,0,TimeUnit.MILLISECONDS); // try to put object into array, but don't wait
}catch(InterruptedException ie){
ie.printStackTrace();
return false;
}
}
public boolean offer(Object v,long timeout,TimeUnit unit)throws InterruptedException{
if(v==null){
throw new NullPointerException(getClass().getName()+".offer(Object v,long timeout,TimeUnit unit)\n\tObject v is null.");
}
if(empty.tryAcquire(timeout,unit)){
synchronized(pt){add(v);}
full.release();
return true;
}
return false;
}
protected Object remove(){
Object v=buffer[front];
front++;if(front>=size){front-=size;fcarry=!fcarry;}
return v;
}
public Object take()throws InterruptedException{
Object v;
full.acquire();
synchronized(gt){v=remove();}
empty.release();
return v;
}
public Object poll(){
try{
return poll(0,TimeUnit.MILLISECONDS); // try to get object, but don't wait
}catch(InterruptedException ie){
ie.printStackTrace();
return null;
}
}
public Object poll(long timeout,TimeUnit unit)throws InterruptedException{
Object v=null;
if(full.tryAcquire(timeout,unit)){ // if we get a permit
synchronized(gt){v=remove();} // get Object
empty.release();
} // else return null
return v;
}
public void clear(){while(poll()!=null){}}
}