[ 
https://issues.apache.org/jira/browse/POOL-132?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Mark Thomas resolved POOL-132.
------------------------------

    Resolution: Duplicate

This was fixed by the combined patch for POOL-93 / POOL-108

> GenericKeyedObjectPool.borrowObject(Object key) blocked for all threads until 
> _factory.makeObject(key) is finished
> ------------------------------------------------------------------------------------------------------------------
>
>                 Key: POOL-132
>                 URL: https://issues.apache.org/jira/browse/POOL-132
>             Project: Commons Pool
>          Issue Type: Improvement
>    Affects Versions: 1.4
>            Reporter: Michael Mueller
>            Priority: Minor
>             Fix For: 1.5
>
>
> If no Object is in the pool the method 
> GenericKeyedObjectPool.borrowObject(Object key) is blocking until a new 
> Object (_factory.makeObject(key) ) is created.  This will block all other 
> threads even if they want an Object for a different key or want return an 
> Object.
> The GenericObjectPool.borrowObject() have a better implementation where the 
> _factory.makeObject(key)  is called after the synchronized block.
> Could this changed like this?
> {code:title=GenericKeyedObjectPool.borrowObject(Object key)|borderStyle=solid}
>     public Object borrowObject(Object key) throws Exception {
>         long starttime = System.currentTimeMillis();
>         
>         for(;;) {
>             ObjectTimestampPair pair = null;
>             ObjectQueue pool = null;
>             synchronized (this) {
>                 assertOpen();
>                 pool = (ObjectQueue)(_poolMap.get(key));
>                 if(null == pool) {
>                     pool = new ObjectQueue();
>                     _poolMap.put(key,pool);
>                     _poolList.add(key);
>                 }
>                 // if there are any sleeping, just grab one of those
>                 try {
>                     pair = (ObjectTimestampPair)(pool.queue.removeFirst());
>                     if(null != pair) {
>                         _totalIdle--;
>                     }
>                 } catch(NoSuchElementException e) { /* ignored */
>                 }
>                 // otherwise
>                 if(null == pair) {
>                     // if there is a totalMaxActive and we are at the limit 
> then
>                     // we have to make room
>                     if ((_maxTotal > 0) && (_totalActive + _totalIdle >= 
> _maxTotal)) {
>                         clearOldest();
>                     }
>     
>                     // check if we can create one
>                     // (note we know that the num sleeping is 0, else we 
> wouldn't be here)
>                     if ((_maxActive < 0 || pool.activeCount < _maxActive) &&
>                         (_maxTotal < 0 || _totalActive + _totalIdle < 
> _maxTotal)) {
>                         // allow new object to be created
>                     } else {
>                         // the pool is exhausted
>                         switch(_whenExhaustedAction) {
>                             case WHEN_EXHAUSTED_GROW:
>                                 // allow new object to be created
>                                 break;
>                             case WHEN_EXHAUSTED_FAIL:
>                                 throw new NoSuchElementException();
>                             case WHEN_EXHAUSTED_BLOCK:
>                                 try {
>                                     if(_maxWait <= 0) {
>                                         wait();
>                                     } else {
>                                         // this code may be executed again 
> after a notify then continue cycle
>                                         // so, need to calculate the amount 
> of time to wait
>                                         final long elapsed = 
> (System.currentTimeMillis() - starttime);
>                                         final long waitTime = _maxWait - 
> elapsed;
>                                         if (waitTime > 0)
>                                         {
>                                             wait(waitTime);
>                                         }
>                                     }
>                                 } catch(InterruptedException e) {
>                                     // ignored
>                                 }
>                                 if(_maxWait > 0 && 
> ((System.currentTimeMillis() - starttime) >= _maxWait)) {
>                                     throw new NoSuchElementException("Timeout 
> waiting for idle object");
>                                 } else {
>                                     continue; // keep looping
>                                 }
>                             default:
>                                 throw new 
> IllegalArgumentException("whenExhaustedAction " + _whenExhaustedAction + " 
> not recognized.");
>                         }
>                     }
>                 }
>                 pool.incrementActiveCount();
>             }
>             
>             // create new object when needed
>             boolean newlyCreated = false;
>             if(null == pair) {
>                 try {
>                     Object obj = _factory.makeObject();
>                     pair = new ObjectTimestampPair(obj);
>                     newlyCreated = true;
>                 } finally {
>                     if (!newlyCreated) {
>                         // object cannot be created
>                         synchronized (this) {
>                             pool.decrementActiveCount();                      
>       
>                         }
>                     }
>                 }
>             }
>             
>             // Activate.  If activate fails, decrement active count and 
> destroy.
>             // If instance failing activation is new, throw 
> NoSuchElementException;
>             // otherwise keep looping
>             try {
>                 _factory.activateObject(key, pair.value);
>             } catch (Exception e) {
>                 try {
>                     _factory.destroyObject(key,pair.value);
>                     synchronized (this) {
>                         pool.decrementActiveCount();
>                     }
>                 } catch (Exception e2) {
>                     // swallowed
>                 }
>                 if(newlyCreated) {
>                     throw new NoSuchElementException(
>                        "Could not create a validated object, cause: "
>                             + e.getMessage());
>                 }
>                 else {
>                     continue; // keep looping
>                 }
>             }
>             // Validate.  If validation fails, decrement active count and
>             // destroy. If instance failing validation is new, throw
>             // NoSuchElementException; otherwise keep looping
>             boolean invalid = true;
>             try {
>                 invalid = _testOnBorrow && !_factory.validateObject(key, 
> pair.value);
>             } catch (Exception e) {
>                 // swallowed
>             }
>             if (invalid) {
>                 try {
>                     _factory.destroyObject(key,pair.value);
>                     synchronized (this) {
>                         pool.decrementActiveCount();
>                     }
>                 } catch (Exception e) {
>                     // swallowed
>                 }
>                 if(newlyCreated) {
>                     throw new NoSuchElementException("Could not create a 
> validated object");
>                 } // else keep looping
>             } else {
>                 return pair.value;
>             }
>         }
>     }
> {code} 

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to