What is object pool?
As a developer we might have noticed that creation of some class is very
difficult and number of time that we need to create. Such object creation every
time is very expensive in terms of system resources. If we can cache that kind
of object show how will surely boost the application performance and resource
usage can be saved. This where object pool design pattern will help development
community to cache the objects. Some time it is also called as Object cache or
Resource cache design pattern.
It is adviced to keep all Reusable expensive objects that are not currently in
use in the container so that they can be managed by one rational policy. To
achieve this, the Reusable Pool class is designed to be a singleton class.
Support of C# for pooling objects
Queue Class
Queue is a Simple DataStucture which allows Add or Remove of Items at one of the
ends only. It is basically called as First in First out data structure. The item
which is added first is the first one to be removed. Default initial size of the
queue is 32. Make sure that whenever Queue is initialized define the size of the
queue, that Add and Remove operations are performed perfectly.
Enqueue () method will add the item in the last available portion and Dequeue ()
method will remove and return the oldest item in the queue. Set us see the code
how it helps to implement the object pool design pattern.
EX: Simple Example
public
class QueuedPool:
Queue
{
public Person
Fetch()
{
return (Person)Dequeue();
}
public void
Store(Person person)
{
Enqueue(person);
}
public void
ClearAll()
{
base.Clear();
}
}
At client side
QueuedPool
queuePool = new
QueuedPool();
queuePool.Store(new
Person());
Person
p = queuePool.Fetch();
EX: Using Generics
public
interface IStore<T>
{
T Fetch();
void Store(T obj);
int Count { get;}
void ClearAll();
}
public
class QueuedPool<T>
: Queue<T>, IStore<T>
{
public T Fetch()
{
return (T)Dequeue();
}
public void
Store(T obj)
{
Enqueue(obj);
}
public void
ClearAll()
{
base.Clear();
}
}
At client side
QueuedPool<Person>
queuePool = new
QueuedPool<Person>();
queuePool.Store(new
Person());
Person
p = queuePool.Fetch();
EX: Thread safe Example
public
sealed class
ObjectPoolObject<T>
where T : new()
{
private
readonly int _poolSize;
private
readonly object _threadLocker;
private
readonly Queue<T> _poolManager;
public ObjectPoolObject(int
expectedPoolSize)
{
if (expectedPoolSize <= 0)
throw
new ArgumentOutOfRangeException("expectedPoolSize",
"Pool size can't be null or zero or less than zero");
_poolManager =
new Queue<T>();
_threadLocker = new
object();
_poolSize = expectedPoolSize;
}
public T Get()
{
lock (_threadLocker)
{
if (_poolManager.Count > 0)
{
return _poolManager.Dequeue();
}
else
{
return
new T();
}
}
}
public int
Count()
{
return _poolManager.Count;
}
public void
Put(T obj)
{
lock(_threadLocker)
{
if (_poolManager.Count < _poolSize)
_poolManager.Enqueue(obj);
}
}
}
At client side
ObjectPoolObject<Person>
personPoolObject = new
ObjectPoolObject<Person>(10);
Person
a = personPoolObject.Get();
Person
a1 = personPoolObject.Get();
addressPoolObject.Put(a);
addressPoolObject.Put(a1);
Best candidates for
1. Any ticketing counter, who goes first those, gets ticks first.
2. Who places order first they get served first.
Now let us continue with other options available in C#
Stack Class
The Stack class implements a Last in First Out data structure. The objects are
stored in such a manner that the object added last is placed at the top of the
stack.
Push () method adds new item to stack on the top of all items. Pop () method
removes the top item in the items list.
public
class StackPool<T>:
Stack<T>, IStore<T>
{
public T Fetch()
{
return Pop();
}
public void
Store(T obj)
{
Push(obj);
}
public void
ClearAll()
{
Clear();
}
}
At client
StackPool<Person>
personStackPool = new
StackPool<Person>();
personStackPool.Store(new
Address());
personStackPool.Store(new
Address());
Person
p1 = personStackPool.Fetch();
Person
p2 = personStackPool.Fetch();
Singleton Example
public
sealed class
ObjectPoolObject<T>
where T : new()
{
private
readonly object _threadLocker =
new object();
private
readonly Queue<T> _poolManager =
new Queue<T>();
private static
ObjectPoolObject<T> _objectPoolObject;
private ObjectPoolObject() { }
static ObjectPoolObject()
{
_objectPoolObject = new
ObjectPoolObject<T>();
}
public static
ObjectPoolObject<T> GetInstance()
{
return _objectPoolObject;
}
public T Get()
{
lock (_threadLocker)
{
if (_poolManager.Count > 0)
{
return _poolManager.Dequeue();
}
else
{
return
new T();
}
}
}
public int
Count()
{
return _poolManager.Count;
}
public void
Put(T obj)
{
lock(_threadLocker)
{
_poolManager.Enqueue(obj);
}
}
}
public
class Person
{
private string
_firstName;
private string
_middleInitial;
private string
_lastName;
public string
FirstName
{
get {
return _firstName;}
set { _firstName =
value; }
}
public string
MiddleInitial
{
get {
return _middleInitial;}
set { _middleInitial =
value; }
}
public string
LastName
{
get {
return _lastName;}
set { _lastName =
value; }
}
public Person() { }
}