I'm trying to implement TCP connection pooling and return a connection back to the pool using IDisposable
. I'm wondering if my implementation is correct. It seems to be working but I think because the base class also implements IDisposable
and finalize, my code might be leaky.
public class BaseClass : IDisposable
{
internal bool IsDisposed { get; set; }
private object someResource;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~BaseClass()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (someResource != null)
{
// some clearn up
return;
}
if (disposing)
{
//dispose un managed resources
}
}
}
public class ChildClass : BaseClass
{
// adds some functionality
}
public class MyClass : ChildClass, IDisposable
{
MyPoolManager manager = null;
public MyClass(MyPoolManager manager)
{
this.manager = manager;
}
void IDisposable.Dispose()
{
manager.ReturnPooledConnection(this);
}
}
public class MyPoolManager
{
private static MyPoolManager instance = new MyPoolManager();
private static object objLock = new object();
private static Queue<MyClass> que = null;
private string name;
static MyPoolManager()
{
que = new Queue<MyClass>();
// enqueue some instances of MyClass here
MyClass client = new MyClass(instance);
que.Enqueue(client);
}
private MyPoolManager() { }
public MyPoolManager(string name)
{
this.name = name;
}
public MyClass GetPooledConnection()
{
lock (objLock)
{
while (que.Count == 0)
{
if (!Monitor.Wait(objLock, 1000))
throw new TimeoutException("Connection timeout");
}
return que.Dequeue();
}
}
public void ReturnPooledConnection(MyClass client)
{
lock (objLock)
{
que.Enqueue(client);
Monitor.Pulse(objLock);
}
}
}
Use it like this in your program:
MyPoolManager pool = new MyPoolManager();
using (var conn = pool.GetPooledConnection())
{
// use the conn here
}
// when you reach here the conn should have returned back to the pool
internal bool IsDisposed { get; private set; }
. \$\endgroup\$