Pop() private method

private Pop ( ) : Object
return Object
        /// <summary>
        /// Cleans up everything in both the old and new stack.  If a connection is in use
        /// then it will be on neither stack and it is the responsibility of the object
        /// using that connection to clean it up when it is finished using it.  This does
        /// not clean up the ConnectionPool object and new connections can still be
        /// created if needed in the future should this ConnectionPool object be reused
        ///
        /// preconditions: none
        ///
        /// postconditions: any connections not currently in use by an object will be
        /// gracefully terminated and purged from this connection pool
        /// </summary>
        internal void ForceCleanup()
        {
            if (Logging.On)
            {
                Logging.Enter(Logging.Web, "ConnectionPool::ForceCleanup");
            }

            // If WaitOne returns false, all connections in the pool are in use
            // so no cleanup should be performed. The last object owning
            // a connection from the pool will perform final cleanup.
            while (Count > 0)
            {
                if (Semaphore.WaitOne(0, false))
                {
                    // Try to clean up from new stack first, if there isn't anything on new
                    // then try old.  When we lock the Semaphore, it gives us a license to
                    // remove only one connection from the pool but it can be from either
                    // stack since if the Semaphore is locked by another thread it means that
                    // there must have been more than one connection available in either stack
                    PooledStream pooledStream = (PooledStream)m_StackNew.Pop();

                    // no streams in stack new, there must therefore be one in stack old since we
                    // were able to acquire the semaphore
                    if (pooledStream == null)
                    {
                        pooledStream = (PooledStream)m_StackOld.Pop();
                    }

                    Debug.Assert(pooledStream != null, "Acquired Semaphore with no connections in either stack");
                    Destroy(pooledStream);
                }
                else
                {
                    // couldn't get semaphore, nothing to do here
                    break;
                }
            }

            if (Logging.On)
            {
                Logging.Exit(Logging.Web, "ConnectionPool::ForceCleanup");
            }
        }
        /// <summary>
        ///    <para>This is called by a timer, to check for needed cleanup of idle pooled streams</para>
        /// </summary>
        private void CleanupCallback()
        {
            // Called when the cleanup-timer ticks over.
            //
            // This is the automatic prunning method.  Every period, we will perform a two-step
            // process.  First, for the objects above MinPool, we will obtain the semaphore for
            // the object and then destroy it if it was on the old stack.  We will continue this
            // until we either reach MinPool size, or we are unable to obtain a free object, or
            // until we have exhausted all the objects on the old stack.  After that, push all
            // objects on the new stack to the old stack.  So, every period the objects on the
            // old stack are destroyed and the objects on the new stack are pushed to the old
            // stack.  All objects that are currently out and in use are not on either stack.
            // With this logic, a object is prunned if unused for at least one period but not
            // more than two periods.

            // Destroy free objects above MinPool size from old stack.
            while (Count > MinPoolSize)  // While above MinPoolSize...

            {
                if (Semaphore.WaitOne(0, false))    // != WaitTimeout
                // We obtained a objects from the semaphore.
                {
                    PooledStream pooledStream = (PooledStream)m_StackOld.Pop();

                    if (null != pooledStream)
                    {
                        // If we obtained one from the old stack, destroy it.
                        Destroy(pooledStream);
                    }
                    else
                    {
                        // Else we exhausted the old stack, so break.
                        Semaphore.ReleaseSemaphore();
                        break;
                    }
                }
                else
                {
                    break;
                }
            }

            // Push to the old-stack.  For each free object, move object from new stack
            // to old stack.
            if (Semaphore.WaitOne(0, false))  //  != WaitTimeout
            {
                for (;;)
                {
                    PooledStream pooledStream = (PooledStream)m_StackNew.Pop();

                    if (null == pooledStream)
                    {
                        break;
                    }

                    GlobalLog.Assert(!pooledStream.IsEmancipated, "Pooled object not in pool.");
                    GlobalLog.Assert(pooledStream.CanBePooled, "Pooled object is not poolable.");

                    m_StackOld.Push(pooledStream);
                }
                Semaphore.ReleaseSemaphore();
            }
        }