public byte[] GetBuffer()
{
Object cookie = null;
try
{
// If a ThreadAbortException gets thrown after the exchange,
// but before the result is assigned to cookie, then the
// control cookie is lost forever. However, the buffer pool
// will still function normally and return everybody a new
// buffer each time (that isn't very likely to happen,
// so we don't really care).
cookie = Interlocked.Exchange(ref _controlCookie, null);
if (cookie != null)
{
// we have the control cookie, so take a buffer
if (_current == -1)
{
_controlCookie = cookie;
// no pooled buffers available
return new byte[_bufferSize];
}
else
{
// grab next available buffer
byte[] buffer = _bufferPool[_current];
_bufferPool[_current] = null;
// update "current" index
if (_current == _last)
{
// this is the last free buffer
_current = -1;
}
else
{
_current = (_current + 1) % _max;
}
_controlCookie = cookie;
return buffer;
}
}
else
{
// we don't have the control cookie, so just create a new buffer since
// there will probably be a lot of contention anyway.
return new byte[_bufferSize];
}
}
catch (ThreadAbortException)
{
if (cookie != null)
{
// This should be rare, so just reset
// everything to the initial state.
_current = -1;
_last = -1;
// restore cookie
_controlCookie = cookie;
}
throw;
}
} // GetBuffer