Save This Page
Home » commons-pool-1.5.4-src » org.apache.commons » pool » impl » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   package org.apache.commons.pool.impl;
   19   
   20   import java.lang.ref.SoftReference;
   21   import java.lang.ref.ReferenceQueue;
   22   import java.lang.ref.Reference;
   23   import java.util.ArrayList;
   24   import java.util.Iterator;
   25   import java.util.List;
   26   import java.util.NoSuchElementException;
   27   
   28   import org.apache.commons.pool.BaseObjectPool;
   29   import org.apache.commons.pool.ObjectPool;
   30   import org.apache.commons.pool.PoolableObjectFactory;
   31   import org.apache.commons.pool.PoolUtils;
   32   
   33   /**
   34    * A {@link java.lang.ref.SoftReference SoftReference} based
   35    * {@link ObjectPool}.
   36    *
   37    * @author Rodney Waldhoff
   38    * @author Sandy McArthur
   39    * @version $Revision: 777748 $ $Date: 2009-05-22 20:00:44 -0400 (Fri, 22 May 2009) $
   40    * @since Pool 1.0
   41    */
   42   public class SoftReferenceObjectPool extends BaseObjectPool implements ObjectPool {
   43       /**
   44        * Create a <code>SoftReferenceObjectPool</code> without a factory.
   45        * {@link #setFactory(PoolableObjectFactory) setFactory} should be called
   46        * before any attempts to use the pool are made.
   47        * Generally speaking you should prefer the {@link #SoftReferenceObjectPool(PoolableObjectFactory)} constructor.
   48        *
   49        * @see #SoftReferenceObjectPool(PoolableObjectFactory)
   50        */
   51       public SoftReferenceObjectPool() {
   52           _pool = new ArrayList();
   53           _factory = null;
   54       }
   55   
   56       /**
   57        * Create a <code>SoftReferenceObjectPool</code> with the specified factory.
   58        *
   59        * @param factory object factory to use.
   60        */
   61       public SoftReferenceObjectPool(PoolableObjectFactory factory) {
   62           _pool = new ArrayList();
   63           _factory = factory;
   64       }
   65   
   66       /**
   67        * Create a <code>SoftReferenceObjectPool</code> with the specified factory and initial idle object count.
   68        *
   69        * @param factory object factory to use.
   70        * @param initSize initial size to attempt to prefill the pool.
   71        * @throws Exception when there is a problem prefilling the pool.
   72        * @throws IllegalArgumentException when <code>factory</code> is <code>null</code>.
   73        * @deprecated because this is a SoftReference pool, prefilled idle obejects may be garbage collected before they are used.
   74        *      To be removed in Pool 3.0.
   75        */
   76       public SoftReferenceObjectPool(PoolableObjectFactory factory, int initSize) throws Exception, IllegalArgumentException {
   77           if (factory == null) {
   78               throw new IllegalArgumentException("factory required to prefill the pool.");
   79           }
   80           _pool = new ArrayList(initSize);
   81           _factory = factory;
   82           PoolUtils.prefill(this, initSize);
   83       }
   84   
   85       public synchronized Object borrowObject() throws Exception {
   86           assertOpen();
   87           Object obj = null;
   88           boolean newlyCreated = false;
   89           while(null == obj) {
   90               if(_pool.isEmpty()) {
   91                   if(null == _factory) {
   92                       throw new NoSuchElementException();
   93                   } else {
   94                       newlyCreated = true;
   95                       obj = _factory.makeObject();
   96                   }
   97               } else {
   98                   SoftReference ref = (SoftReference)(_pool.remove(_pool.size() - 1));
   99                   obj = ref.get();
  100                   ref.clear(); // prevent this ref from being enqueued with refQueue.
  101               }
  102               if (null != _factory && null != obj) {
  103                   try {
  104                       _factory.activateObject(obj);
  105                       if (!_factory.validateObject(obj)) {
  106                           throw new Exception("ValidateObject failed");
  107                       }
  108                   } catch (Throwable t) {
  109                       try {
  110                           _factory.destroyObject(obj);
  111                       } catch (Throwable t2) {
  112                           // swallowed
  113                       } finally {
  114                           obj = null;
  115                       }
  116                       if (newlyCreated) {
  117                           throw new NoSuchElementException(
  118                               "Could not create a validated object, cause: " +
  119                               t.getMessage());
  120                       }
  121                   }
  122               }
  123           }
  124           _numActive++;
  125           return obj;
  126       }
  127   
  128       public synchronized void returnObject(Object obj) throws Exception {
  129           boolean success = !isClosed();
  130           if (_factory != null) {
  131               if(!_factory.validateObject(obj)) {
  132                   success = false;
  133               } else {
  134                   try {
  135                       _factory.passivateObject(obj);
  136                   } catch(Exception e) {
  137                       success = false;
  138                   }
  139               }
  140           }
  141   
  142           boolean shouldDestroy = !success;
  143           _numActive--;
  144           if(success) {
  145               _pool.add(new SoftReference(obj, refQueue));
  146           }
  147           notifyAll(); // _numActive has changed
  148   
  149           if (shouldDestroy && _factory != null) {
  150               try {
  151                   _factory.destroyObject(obj);
  152               } catch(Exception e) {
  153                   // ignored
  154               }
  155           }
  156       }
  157   
  158       public synchronized void invalidateObject(Object obj) throws Exception {
  159           _numActive--;
  160           if (_factory != null) {
  161               _factory.destroyObject(obj);
  162           }
  163           notifyAll(); // _numActive has changed
  164       }
  165   
  166       /**
  167        * Create an object, and place it into the pool.
  168        * addObject() is useful for "pre-loading" a pool with idle objects.
  169        */
  170       public synchronized void addObject() throws Exception {
  171           assertOpen();
  172           if (_factory == null) {
  173               throw new IllegalStateException("Cannot add objects without a factory.");
  174           }
  175           Object obj = _factory.makeObject();
  176   
  177           boolean success = true;
  178           if(!_factory.validateObject(obj)) {
  179               success = false;
  180           } else {
  181               _factory.passivateObject(obj);
  182           }
  183   
  184           boolean shouldDestroy = !success;
  185           if(success) {
  186               _pool.add(new SoftReference(obj, refQueue));
  187               notifyAll(); // _numActive has changed
  188           }
  189   
  190           if(shouldDestroy) {
  191               try {
  192                   _factory.destroyObject(obj);
  193               } catch(Exception e) {
  194                   // ignored
  195               }
  196           }
  197       }
  198   
  199       /** Returns an approximation not less than the of the number of idle instances in the pool. */
  200       public synchronized int getNumIdle() {
  201           pruneClearedReferences();
  202           return _pool.size();
  203       }
  204   
  205       /**
  206        * Return the number of instances currently borrowed from this pool.
  207        *
  208        * @return the number of instances currently borrowed from this pool
  209        */
  210       public synchronized int getNumActive() {
  211           return _numActive;
  212       }
  213   
  214       /**
  215        * Clears any objects sitting idle in the pool.
  216        */
  217       public synchronized void clear() {
  218           if(null != _factory) {
  219               Iterator iter = _pool.iterator();
  220               while(iter.hasNext()) {
  221                   try {
  222                       Object obj = ((SoftReference)iter.next()).get();
  223                       if(null != obj) {
  224                           _factory.destroyObject(obj);
  225                       }
  226                   } catch(Exception e) {
  227                       // ignore error, keep destroying the rest
  228                   }
  229               }
  230           }
  231           _pool.clear();
  232           pruneClearedReferences();
  233       }
  234   
  235       public void close() throws Exception {
  236           super.close();
  237           clear();
  238       }
  239   
  240       /**
  241        * Sets the {@link PoolableObjectFactory factory} this pool uses
  242        * to create new instances. Trying to change
  243        * the <code>factory</code> while there are borrowed objects will
  244        * throw an {@link IllegalStateException}.
  245        *
  246        * @param factory the {@link PoolableObjectFactory} used to create new instances.
  247        * @throws IllegalStateException when the factory cannot be set at this time
  248        */
  249       public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException {
  250           assertOpen();
  251           if(0 < getNumActive()) {
  252               throw new IllegalStateException("Objects are already active");
  253           } else {
  254               clear();
  255               _factory = factory;
  256           }
  257       }
  258   
  259       /**
  260        * If any idle objects were garbage collected, remove their
  261        * {@link Reference} wrappers from the idle object pool.
  262        */
  263       private void pruneClearedReferences() {
  264           Reference ref;
  265           while ((ref = refQueue.poll()) != null) {
  266               try {
  267                   _pool.remove(ref);
  268               } catch (UnsupportedOperationException uoe) {
  269                   // ignored
  270               }
  271           }
  272       }
  273   
  274       /** My pool. */
  275       private List _pool = null;
  276   
  277       /** My {@link PoolableObjectFactory}. */
  278       private PoolableObjectFactory _factory = null;
  279   
  280       /**
  281        * Queue of broken references that might be able to be removed from <code>_pool</code>.
  282        * This is used to help {@link #getNumIdle()} be more accurate with minimial
  283        * performance overhead.
  284        */
  285       private final ReferenceQueue refQueue = new ReferenceQueue();
  286   
  287       /** Number of active objects. */
  288       private int _numActive = 0;
  289   }

Save This Page
Home » commons-pool-1.5.4-src » org.apache.commons » pool » impl » [javadoc | source]