public T borrow ( long timeout , final TimeUnit timeUnit ) throws InterruptedException { // Try the thread-local list first final List < Object > list = threadList . get ( ) ; for ( int i = list . size ( ) - 1 ; i >= 0 ; i -- ) { final Object entry = list . remove ( i ) ; @ SuppressWarnings ( "unchecked" ) final T bagEntry = weakThreadLocals ? ( ( WeakReference < T > ) entry ) . get ( ) : ( T ) entry ; if ( bagEntry != null && bagEntry . compareAndSet ( STATE_NOT_IN_USE , STATE_IN_USE ) ) { return bagEntry ; } } // Otherwise, scan the shared list ... then poll the handoff queue final int waiting = waiters . incrementAndGet ( ) ; try { for ( T bagEntry : sharedList ) { if ( bagEntry . compareAndSet ( STATE_NOT_IN_USE , STATE_IN_USE ) ) { // If we may have stolen another waiter's connection, request another bag add. if ( waiting > 1 ) { listener . addBagItem ( waiting - 1 ) ; } return bagEntry ; } } listener . addBagItem ( waiting ) ; timeout = timeUnit . toNanos ( timeout ) ; do { final long start = currentTime ( ) ; final T bagEntry = handoffQueue . poll ( timeout , NANOSECONDS ) ; if ( bagEntry == null || bagEntry . compareAndSet ( STATE_NOT_IN_USE , STATE_IN_USE ) ) { return bagEntry ; } timeout -= elapsedNanos ( start ) ; } while ( timeout > 10_000 ) ; return null ; } finally { waiters . decrementAndGet ( ) ; } }
The method will borrow a BagEntry from the bag blocking for the specified timeout if none are available .