private void EnumEntries(IEnumerator <E> it, PoolEntryCallback <T, C> callback)
 {
     while (it.HasNext())
     {
         E entry = it.Next();
         callback.Process(entry);
         if (entry.IsClosed())
         {
             RouteSpecificPool <T, C, E> pool = GetPool(entry.GetRoute());
             pool.Remove(entry);
             it.Remove();
         }
     }
 }
        /// <exception cref="System.IO.IOException"></exception>
        /// <exception cref="System.Exception"></exception>
        /// <exception cref="Sharpen.TimeoutException"></exception>
        private E GetPoolEntryBlocking(T route, object state, long timeout, TimeUnit tunit
                                       , PoolEntryFuture <E> future)
        {
            DateTime deadline = null;

            if (timeout > 0)
            {
                deadline = Sharpen.Extensions.CreateDate(Runtime.CurrentTimeMillis() + tunit.ToMillis
                                                             (timeout));
            }
            this.Lock.Lock();
            try
            {
                RouteSpecificPool <T, C, E> pool = GetPool(route);
                E entry = null;
                while (entry == null)
                {
                    Asserts.Check(!this.isShutDown, "Connection pool shut down");
                    for (; ;)
                    {
                        entry = pool.GetFree(state);
                        if (entry == null)
                        {
                            break;
                        }
                        if (entry.IsClosed() || entry.IsExpired(Runtime.CurrentTimeMillis()))
                        {
                            entry.Close();
                            this.available.Remove(entry);
                            pool.Free(entry, false);
                        }
                        else
                        {
                            break;
                        }
                    }
                    if (entry != null)
                    {
                        this.available.Remove(entry);
                        this.leased.AddItem(entry);
                        return(entry);
                    }
                    // New connection is needed
                    int maxPerRoute = GetMax(route);
                    // Shrink the pool prior to allocating a new connection
                    int excess = Math.Max(0, pool.GetAllocatedCount() + 1 - maxPerRoute);
                    if (excess > 0)
                    {
                        for (int i = 0; i < excess; i++)
                        {
                            E lastUsed = pool.GetLastUsed();
                            if (lastUsed == null)
                            {
                                break;
                            }
                            lastUsed.Close();
                            this.available.Remove(lastUsed);
                            pool.Remove(lastUsed);
                        }
                    }
                    if (pool.GetAllocatedCount() < maxPerRoute)
                    {
                        int totalUsed    = this.leased.Count;
                        int freeCapacity = Math.Max(this.maxTotal - totalUsed, 0);
                        if (freeCapacity > 0)
                        {
                            int totalAvailable = this.available.Count;
                            if (totalAvailable > freeCapacity - 1)
                            {
                                if (!this.available.IsEmpty())
                                {
                                    E lastUsed = this.available.RemoveLast();
                                    lastUsed.Close();
                                    RouteSpecificPool <T, C, E> otherpool = GetPool(lastUsed.GetRoute());
                                    otherpool.Remove(lastUsed);
                                }
                            }
                            C conn = this.connFactory.Create(route);
                            entry = pool.Add(conn);
                            this.leased.AddItem(entry);
                            return(entry);
                        }
                    }
                    bool success = false;
                    try
                    {
                        pool.Queue(future);
                        this.pending.AddItem(future);
                        success = future.Await(deadline);
                    }
                    finally
                    {
                        // In case of 'success', we were woken up by the
                        // connection pool and should now have a connection
                        // waiting for us, or else we're shutting down.
                        // Just continue in the loop, both cases are checked.
                        pool.Unqueue(future);
                        this.pending.Remove(future);
                    }
                    // check for spurious wakeup vs. timeout
                    if (!success && (deadline != null) && (deadline.GetTime() <= Runtime.CurrentTimeMillis
                                                               ()))
                    {
                        break;
                    }
                }
                throw new TimeoutException("Timeout waiting for connection");
            }
            finally
            {
                this.Lock.Unlock();
            }
        }