@@ -218,7 +218,7 @@ public void addObject() throws Exception {
218218 if (factory == null ) {
219219 throw new IllegalStateException ("Cannot add objects without a factory." );
220220 }
221- addIdleObject (create ());
221+ addIdleObject (create (getMaxWaitDuration () ));
222222 }
223223
224224 /**
@@ -282,46 +282,42 @@ public T borrowObject() throws Exception {
282282 */
283283 public T borrowObject (final Duration borrowMaxWaitDuration ) throws Exception {
284284 assertOpen ();
285-
285+ final Instant startInstant = Instant .now ();
286+ final boolean negativeDuration = borrowMaxWaitDuration .isNegative ();
287+ Duration remainingWaitDuration = borrowMaxWaitDuration ;
286288 final AbandonedConfig ac = this .abandonedConfig ;
287- if (ac != null && ac .getRemoveAbandonedOnBorrow () && getNumIdle () < 2 &&
288- getNumActive () > getMaxTotal () - 3 ) {
289+ if (ac != null && ac .getRemoveAbandonedOnBorrow () && getNumIdle () < 2 && getNumActive () > getMaxTotal () - 3 ) {
289290 removeAbandoned (ac );
290291 }
291-
292292 PooledObject <T > p = null ;
293-
294293 // Get local copy of current config so it is consistent for entire
295294 // method execution
296295 final boolean blockWhenExhausted = getBlockWhenExhausted ();
297-
298296 boolean create ;
299- final Instant waitTime = Instant .now ();
300-
301297 while (p == null ) {
298+ remainingWaitDuration = remainingWaitDuration .minus (durationSince (startInstant ));
302299 create = false ;
303300 p = idleObjects .pollFirst ();
304301 if (p == null ) {
305- p = create ();
302+ p = create (remainingWaitDuration );
306303 if (!PooledObject .isNull (p )) {
307304 create = true ;
308305 }
309306 }
310307 if (blockWhenExhausted ) {
311308 if (PooledObject .isNull (p )) {
312- p = borrowMaxWaitDuration . isNegative () ? idleObjects .takeFirst () : idleObjects .pollFirst (borrowMaxWaitDuration );
309+ p = negativeDuration ? idleObjects .takeFirst () : idleObjects .pollFirst (remainingWaitDuration );
313310 }
314311 if (PooledObject .isNull (p )) {
315312 throw new NoSuchElementException (appendStats (
316- "Timeout waiting for idle object, borrowMaxWaitDuration=" + borrowMaxWaitDuration ));
313+ "Timeout waiting for idle object, borrowMaxWaitDuration=" + remainingWaitDuration ));
317314 }
318315 } else if (PooledObject .isNull (p )) {
319316 throw new NoSuchElementException (appendStats ("Pool exhausted" ));
320317 }
321318 if (!p .allocate ()) {
322319 p = null ;
323320 }
324-
325321 if (!PooledObject .isNull (p )) {
326322 try {
327323 factory .activateObject (p );
@@ -366,12 +362,14 @@ public T borrowObject(final Duration borrowMaxWaitDuration) throws Exception {
366362 }
367363 }
368364 }
369-
370- updateStatsBorrow (p , Duration .between (waitTime , Instant .now ()));
371-
365+ updateStatsBorrow (p , durationSince (startInstant ));
372366 return p .getObject ();
373367 }
374368
369+ private Duration durationSince (final Instant startInstant ) {
370+ return Duration .between (startInstant , Instant .now ());
371+ }
372+
375373 /**
376374 * Borrows an object from the pool using the specific waiting time which only
377375 * applies if {@link #getBlockWhenExhausted()} is true.
@@ -503,19 +501,19 @@ public void close() {
503501 * If the factory makeObject returns null, this method throws a NullPointerException.
504502 * </p>
505503 *
504+ * @param maxWaitDuration The time to wait for an object to become available.
506505 * @return The new wrapped pooled object or null.
507506 * @throws Exception if the object factory's {@code makeObject} fails
508507 */
509- private PooledObject <T > create () throws Exception {
508+ private PooledObject <T > create (final Duration maxWaitDuration ) throws Exception {
510509 int localMaxTotal = getMaxTotal ();
511510 // This simplifies the code later in this method
512511 if (localMaxTotal < 0 ) {
513512 localMaxTotal = Integer .MAX_VALUE ;
514513 }
515514
516515 final Instant localStartInstant = Instant .now ();
517- final Duration maxWaitDurationRaw = getMaxWaitDuration ();
518- final Duration localMaxWaitDuration = maxWaitDurationRaw .isNegative () ? Duration .ZERO : maxWaitDurationRaw ;
516+ final Duration localMaxWaitDuration = maxWaitDuration .isNegative () ? Duration .ZERO : maxWaitDuration ;
519517
520518 // Flag that indicates if create should:
521519 // - TRUE: call the factory to create an object
@@ -549,9 +547,9 @@ private PooledObject<T> create() throws Exception {
549547 }
550548 }
551549
552- // Do not block more if localMaxWaitDuration is set .
550+ // Do not block more if localMaxWaitDuration > 0 .
553551 if (create == null && localMaxWaitDuration .compareTo (Duration .ZERO ) > 0 &&
554- Duration . between (localStartInstant , Instant . now () ).compareTo (localMaxWaitDuration ) >= 0 ) {
552+ durationSince (localStartInstant ).compareTo (localMaxWaitDuration ) >= 0 ) {
555553 create = Boolean .FALSE ;
556554 }
557555 }
@@ -636,7 +634,7 @@ private void ensureIdle(final int idleCount, final boolean always) throws Except
636634 }
637635
638636 while (idleObjects .size () < idleCount ) {
639- final PooledObject <T > p = create ();
637+ final PooledObject <T > p = create (getMaxWaitDuration () );
640638 if (PooledObject .isNull (p )) {
641639 // Can't create objects, no reason to think another call to
642640 // create will work. Give up.
0 commit comments