Skip to content

Instantly share code, notes, and snippets.

@duarten
Created April 29, 2011 12:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save duarten/948237 to your computer and use it in GitHub Desktop.
Save duarten/948237 to your computer and use it in GitHub Desktop.
public interface IBufferPool
{
byte[] TakeBuffer(int size);
void ReturnBuffer(byte[] buffer);
}
public class BufferPoolWithLeakDetection : IBufferPool
{
public class MemoryLeakException : Exception
{
readonly StackTrace _trace;
public MemoryLeakException(StackTrace trace)
{
_trace = trace;
}
public override string Message
{
get { return _trace.ToString(); }
}
~MemoryLeakException()
{
throw this;
}
}
readonly ConditionalWeakTable<byte[], MemoryLeakException> _activeBuffers = new ConditionalWeakTable<byte[], MemoryLeakException>();
readonly IBufferPool _inner;
public BufferPoolWithLeakDetection(IBufferPool inner)
{
_inner = inner;
}
public byte[] TakeBuffer(int size)
{
byte[] buffer = _inner.TakeBuffer(size);
_activeBuffers.Add(buffer, new MemoryLeakException(new StackTrace()));
return buffer;
}
public void ReturnBuffer(byte[] buffer)
{
MemoryLeakException mle;
if (_activeBuffers.TryGetValue(buffer, out mle) == false)
{
throw new ArgumentException();
}
GC.SuppressFinalize(mle);
_activeBuffers.Remove(buffer);
_inner.ReturnBuffer(buffer);
}
}
public class BufferPool : IBufferPool
{
readonly ConcurrentDictionary<int, ConcurrentStack<byte[]>> _pools = new ConcurrentDictionary<int, ConcurrentStack<byte[]>>();
public byte[] TakeBuffer(int size)
{
var stack = _pools.GetOrAdd(size, _ => new ConcurrentStack<byte[]>());
byte[] buffer;
return stack.TryPop(out buffer) ? buffer : new byte[size];
}
public void ReturnBuffer(byte[] buffer)
{
ConcurrentStack<byte[]> pool;
if (_pools.TryGetValue(buffer.Length, out pool) == false)
{
throw new ArgumentException();
}
pool.Push(buffer);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment