/// <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");
}
}