001/* ----------------------------------------------------------------------------
002   The Kiwi Toolkit - A Java Class Library
003   Copyright (C) 1998-2004 Mark A. Lindner
004
005   This library is free software; you can redistribute it and/or
006   modify it under the terms of the GNU General Public License as
007   published by the Free Software Foundation; either version 2 of the
008   License, or (at your option) any later version.
009
010   This library is distributed in the hope that it will be useful,
011   but WITHOUT ANY WARRANTY; without even the implied warranty of
012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013   General Public License for more details.
014
015   You should have received a copy of the GNU General Public License
016   along with this library; if not, write to the Free Software
017   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018   02111-1307, USA.
019 
020   The author may be contacted at: mark_a_lindner@yahoo.com
021   ----------------------------------------------------------------------------
022   $Log: ResourcePool.java,v $
023   Revision 1.5  2004/05/05 21:22:45  markl
024   Comment header updates.
025
026   Revision 1.4  2003/01/19 09:42:39  markl
027   Javadoc & comment header updates.
028
029   Revision 1.3  2001/06/26 06:10:40  markl
030   Fixed typo in javadoc.
031
032   Revision 1.2  2001/03/12 03:16:50  markl
033   *** empty log message ***
034
035   Revision 1.1  1999/04/23 07:33:25  markl
036   Initial revision
037   ----------------------------------------------------------------------------
038*/
039
040package kiwi.util;
041
042import java.util.*;
043
044/** An abstract class that represents a pool of instances of some resource.
045 * See <code>TimerPool</code> for an example concrete implementation. Accesses
046 * to the pool are threadsafe so there is no possibility of contention for
047 * the resource.
048 *
049 * @see kiwi.util.Resource
050 * @see kiwi.util.TimerPool
051 *
052 * @author Mark Lindner
053 */
054
055public abstract class ResourcePool
056  {
057  private int size;
058  private Stack reservedList, availableList;
059
060  /** Construct a new <code>ResourcePool</code> of the given size.
061   *
062   * @param size The number of instances of a resource to preallocate in this
063   * pool.
064   */
065   
066  public ResourcePool(int size)
067    {
068    this.size = size;
069    reservedList = new Stack();
070    availableList = new Stack();
071
072    for(int i = 0; i < size; i++)
073      availableList.push(constructResource());
074    }
075
076  /** Reserve one instance of the resource. If all instances are currently in
077   * use, this method blocks until one becomes available.
078   *
079   * @return An instance of the <code>Resource</code>.
080   */
081   
082  public synchronized Resource reserveResource()
083    {
084    for(;;)
085      {
086      if(!availableList.isEmpty())
087        break;
088      
089      try
090        {
091        System.err.println("All resource instances in use; waiting...");
092        wait();
093        }
094      catch(InterruptedException ex)
095        {
096        }
097      }
098    
099    Resource resource = (Resource)availableList.pop();
100    reservedList.push(resource);
101    resource.reserve();
102
103    return(resource);
104    }
105
106  /** Release the given resource. If the resource is not currently reserved,
107   * this method does nothing. Note that it is the caller's responsibility
108   * to pass the correct resource to this method; the method does not check
109   * if the calling thread actually has the specified resource reserved.
110   *
111   * @param resource The <code>Resource</code> to release.
112    */
113  
114  public synchronized void releaseResource(Resource resource)
115    {
116    if(!(reservedList.contains(resource)))
117      throw(new IllegalArgumentException(
118        "Resource not managed by this pool!"));
119    
120    reservedList.removeElement(resource);
121    resource.release();
122    availableList.push(resource);
123    notify();
124    }
125
126  /** Construct an instance of the resource that is managed by this pool.
127   * The constructor calls this method repeatedly to pre-build the number
128   * of instances specified as its argument.
129   *
130   * @return The newly-constructed <code>Resource</code> instance.
131   */
132   
133  abstract protected Resource constructResource();
134  
135  /** Get the total number of resource instances in this pool.
136   *
137   * @return The total number of instances.
138   */
139  
140  public int getTotalResourceCount()
141    {
142    return(size);
143    }
144
145  /** Get the number of resource instances that are currently in use.
146   *
147   * @return The number of instances that are in use.
148   */
149   
150  public synchronized int getUsedResourceCount()
151    {
152    return(reservedList.size());
153    }
154
155  /** Get the number of resource instances that are currently available.
156   *
157   * @return The number of instances that are available.
158   */
159
160  public synchronized int getAvailableResourceCount()
161    {
162    return(availableList.size());
163    }
164
165  }
166
167/* end of source file */