001package horstmann.ch09_queue2;
002import java.util.ArrayList;
003import java.util.concurrent.locks.Condition;
004import java.util.concurrent.locks.Lock;
005import java.util.concurrent.locks.ReentrantLock;
006
007/**
008    A first-in, first-out bounded collection of objects.
009 */
010public class BoundedQueue<E>
011{
012        /**
013       Constructs an empty queue.
014       @param capacity the maximum capacity of the queue
015         */
016        public BoundedQueue(int capacity)
017        {
018                elements = new ArrayList<E>(capacity);
019                head = 0;
020                tail = 0;
021                size = 0;
022        }
023
024        /**
025       Removes the object at the head.
026       @return the object that has been removed from the queue
027         */
028        public E remove() throws InterruptedException
029        {
030                queueLock.lock();
031                try
032                {
033                        while (size == 0)
034                                valueAvailableCondition.await();
035                        E r = elements.get(head);
036                        head++;
037                        size--;
038                        if (head == elements.size())
039                                head = 0;
040                        spaceAvailableCondition.signalAll();
041                        return r;
042                }
043                finally
044                {
045                        queueLock.unlock();
046                }
047        }
048
049        /**
050       Appends an object at the tail.
051       @param newValue the object to be appended
052         */
053        public void add(E newValue) throws InterruptedException
054        {
055                queueLock.lock();
056                try
057                {
058                        while (size == elements.size())
059                                spaceAvailableCondition.await();
060                        elements.set(tail,newValue);
061                        tail++;
062                        size++;
063                        if (tail == elements.size())
064                                tail = 0;
065                        valueAvailableCondition.signalAll();
066                }
067                finally
068                {
069                        queueLock.unlock();
070                }
071        }
072
073        private ArrayList<E> elements;
074        private int head;
075        private int tail;
076        private int size;
077
078        private Lock queueLock = new ReentrantLock();
079        private Condition spaceAvailableCondition
080        = queueLock.newCondition();
081        private Condition valueAvailableCondition
082        = queueLock.newCondition();
083}