001    package org.apache.fulcrum.pool;
002    
003    
004    /*
005     * Licensed to the Apache Software Foundation (ASF) under one
006     * or more contributor license agreements.  See the NOTICE file
007     * distributed with this work for additional information
008     * regarding copyright ownership.  The ASF licenses this file
009     * to you under the Apache License, Version 2.0 (the
010     * "License"); you may not use this file except in compliance
011     * with the License.  You may obtain a copy of the License at
012     *
013     *   http://www.apache.org/licenses/LICENSE-2.0
014     *
015     * Unless required by applicable law or agreed to in writing,
016     * software distributed under the License is distributed on an
017     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
018     * KIND, either express or implied.  See the License for the
019     * specific language governing permissions and limitations
020     * under the License.
021     */
022    
023    
024    /**
025     * Efficient array-based bounded buffer class.
026     * Adapted from CPJ, chapter 8, which describes design.
027     * Originally written by Doug Lea and released into the public domain.
028     * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>] <p>
029     *
030     * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
031     * @version $Id: BoundedBuffer.java 535465 2007-05-05 06:58:06Z tv $
032     */
033    public class BoundedBuffer
034    {
035        /**
036         * The default capacity.
037         */
038        public static final int DEFAULT_CAPACITY = 1024;
039    
040        protected final Object[]  array_;      // the elements
041    
042        protected int takePtr_ = 0;            // circular indices
043        protected int putPtr_ = 0;
044    
045        protected int usedSlots_ = 0;          // length
046        protected int emptySlots_;             // capacity - length
047    
048        /**
049         * Creates a buffer with the given capacity.
050         *
051         * @param capacity the capacity.
052         * @throws IllegalArgumentException if capacity less or equal to zero.
053         */
054        public BoundedBuffer(int capacity)
055                             throws IllegalArgumentException
056        {
057            if (capacity <= 0)
058               throw new IllegalArgumentException();
059    
060            array_ = new Object[capacity];
061            emptySlots_ = capacity;
062        }
063    
064        /**
065         * Creates a buffer with the default capacity
066         */
067        public BoundedBuffer()
068        {
069            this(DEFAULT_CAPACITY);
070        }
071    
072        /**
073         * Returns the number of elements in the buffer.
074         * This is only a snapshot value, that may change
075         * immediately after returning.
076         *
077         * @return the size.
078         */
079        public synchronized int size()
080        {
081            return usedSlots_;
082        }
083    
084        /**
085         * Returns the capacity of the buffer.
086         *
087         * @return the capacity.
088         */
089        public int capacity()
090        {
091            return array_.length;
092        }
093    
094        /**
095         * Peeks, but does not remove the top item from the buffer.
096         *
097         * @return the object or null.
098         */
099        public synchronized Object peek()
100        {
101            if (usedSlots_ > 0)
102                return array_[takePtr_];
103            else
104                return null;
105        }
106    
107        /**
108         * Puts an item in the buffer only if there is capacity available.
109         *
110         * @param item the item to be inserted.
111         * @return true if accepted, else false.
112         */
113        public synchronized boolean offer(Object x)
114        {
115            if (x == null)
116                throw new IllegalArgumentException();
117    
118            if (emptySlots_ > 0)
119            {
120                --emptySlots_;
121                array_[putPtr_] = x;
122                if (++putPtr_ >= array_.length)
123                    putPtr_ = 0;
124                usedSlots_++;
125                return true;
126            }
127            else
128                return false;
129        }
130    
131        /**
132         * Polls and removes the top item from the buffer if one is available.
133         *
134         * @return the oldest item from the buffer, or null if the buffer is empty.
135         */
136        public synchronized Object poll()
137        {
138            if (usedSlots_ > 0)
139            {
140                --usedSlots_;
141                Object old = array_[takePtr_];
142                array_[takePtr_] = null;
143                if (++takePtr_ >= array_.length)
144                    takePtr_ = 0;
145                emptySlots_++;
146                return old;
147            }
148            else
149                return null;
150        }
151    }