public ISocket GetSocket() {
ThrowIfDisposed();
ISocket socket = null;
lock(_syncroot) {
while(true) {
while(true) {
if(!_availableSockets.Any()) {
break;
}
// take available from end of list
var available = _availableSockets[_availableSockets.Count - 1];
_availableSockets.RemoveAt(_availableSockets.Count - 1);
// if socket is disposed, has been idle for more than 10 seconds or is not Connected
if(!available.Socket.IsDisposed && (available.Queued > DateTime.UtcNow.Add(-CheckInterval) || available.Socket.Connected)) {
socket = available.Socket;
break;
}
// dead socket, clean up and try pool again
if(!available.Socket.IsDisposed) {
available.Socket.Dispose();
}
}
if(socket != null) {
break;
}
if(_availableSockets.Count + _busySockets.Count < MaxConnections) {
socket = _socketFactory();
_log.DebugFormat("created new socket for pool (max: {0}, available: {1}, busy: {2}, queued: {3})",
MaxConnections,
_availableSockets.Count,
_busySockets.Count,
_waitingQueue.Count
);
break;
}
ReapSockets(null);
if(_availableSockets.Count + _busySockets.Count >= MaxConnections) {
break;
}
}
if(socket != null) {
return WrapSocket(socket);
}
}
socket = _waitingQueue.AwaitSocket(ConnectTimeout);
if(socket == null) {
throw new PoolExhaustedException(MaxConnections);
}
return WrapSocket(socket);
}