private PooledStream Get(object owningObject, int result, ref bool continueLoop, ref WaitHandle [] waitHandles) {
PooledStream pooledStream = null;
GlobalLog.Enter("ConnectionPool#" + ValidationHelper.HashString(this) + "::Get", result.ToString());
// From the WaitAny docs: "If more than one object became signaled during
// the call, this is the array index of the signaled object with the
// smallest index value of all the signaled objects." This is important
// so that the free object signal will be returned before a creation
// signal.
switch (result) {
case WaitTimeout:
Interlocked.Decrement(ref m_WaitCount);
continueLoop = false;
GlobalLog.Leave("ConnectionPool#" + ValidationHelper.HashString(this) + "::Get","throw Timeout WebException");
throw new WebException(NetRes.GetWebStatusString("net_timeout", WebExceptionStatus.ConnectFailure), WebExceptionStatus.Timeout);
case ErrorHandleIndex:
// Throw the error that PoolCreateRequest stashed.
int newWaitCount = Interlocked.Decrement(ref m_WaitCount);
continueLoop = false;
Exception exceptionToThrow = m_ResError;
if (newWaitCount == 0) {
CancelErrorCallback();
}
throw exceptionToThrow;
case CreationHandleIndex:
try {
continueLoop = true;
pooledStream = UserCreateRequest();
if (null != pooledStream) {
pooledStream.PostPop(owningObject);
Interlocked.Decrement(ref m_WaitCount);
continueLoop = false;
}
else {
// If we were not able to create an object, check to see if
// we reached MaxPoolSize. If so, we will no longer wait on
// the CreationHandle, but instead wait for a free object or
// the timeout.
// BUG - if we receive the CreationHandle midway into the wait
// period and re-wait, we will be waiting on the full period
if (Count >= MaxPoolSize && 0 != MaxPoolSize) {
if (!ReclaimEmancipatedObjects()) {
// modify handle array not to wait on creation mutex anymore
waitHandles = new WaitHandle[2];
waitHandles[0] = m_WaitHandles[0];
waitHandles[1] = m_WaitHandles[1];
}
}
}
}
finally {
CreationMutex.ReleaseMutex();
}
break;
default:
//
// guaranteed available inventory
//
Interlocked.Decrement(ref m_WaitCount);
pooledStream = GetFromPool(owningObject);
continueLoop = false;
break;
}
GlobalLog.Leave("ConnectionPool#" + ValidationHelper.HashString(this) + "::Get",ValidationHelper.HashString(pooledStream));
return pooledStream;
}