Skip to content →

A generic pool of objects

Right as this is my first post let’s keep it nice and simple.

A pool works by managing a collection of objects kept in memory so they are always available. A pool can be particularly useful for many situations such as managing large classes which take time to initialise and can help contain classes with memory leaks. There is no correct way to make a pool and it should be optimised to the requirements of the situation.

This pool is designed to recycle a collection of objects:

  • It creates a new object of type T when it is empty.
  • It is important that we only store ONE reference to each instance of an object in the collection, hence the validation in the ReturnToPool() method.
  • The lock() method is used to make this class threadsafe.
  • In most instances such as managing a memory leak, it should be used as a singleton.
  • When an object is ready to be returned it is not the responsibility of this class to do so. (I will make a post in the future about correct ways to do this)
The code:
public class Pool<T>
{
    private readonly Stack<T> _pool = new Stack<T>();
    private readonly Func<T> _createNewFunction;

    public Pool(Func<T> createNewFunction)
    {
        _createNewFunction = createNewFunction;
    }

    public T GetFromPool()
    {
        lock (_pool)
        {
            if (_pool.Count <= 0)
            {
                // Create a new T
                return _createNewFunction();
            }

            return _pool.Pop();
        }
    }

    public void ReturnToPool(T item)
    {
        lock (_pool)
        {
            if (_pool.Contains(item))
            {
                // If it is already in the pool don't re-add it.
                throw new InvalidOperationException("This item is already in the pool");
            }

            _pool.Push(item);
        }
    }
}

Published in Development

3 Comments

  1. Royston Shufflebotham Royston Shufflebotham

    This is a really useful class; here’s a little feedback:

    1. I couldn’t figure out why the class is abstract: it doesn’t declare any abstract methods, and it looks directly useble without needing to be subclassed. (Of course, it could be usefully subclassed, perhaps to work with a T which declares a public default constructor (a : new() constraint) and so which generates the factory delegate for you.)

    2. In ReturnToPool, something has surely gone very wrong with a caller if it returns the same item twice: if the caller does that, then in the middle of those two calls that object is available to be handed out to another caller. If it then gets returned again, we can end up with the same item handed out twice. If a caller is returning items multiple times, that’s potentially a very serious bug waiting to bite you – is it appropriate to fail silently? Blowing up if your .Contains call returns true isn’t guaranteed to find all such problems, but it would help find some of them.

    3. [minor] How many items are you expecting in the pool – the .Contains call in ReturnToPool is O(n), so a Set might be worth considering as the backing store if the expected count is large.

    Great to see this blog arrive (I love the Blend-like styling too) – keep it up!

  2. jc jc

    @Royston Shufflebotham

    Good points, the abstract just snuck in there and was not meant to be there and I have amended the class to throw an exception when a duplicate item is returned.

    As for point 3. I was expecting it to be a relatively small class, but I shall look into this.

  3. Royston Shufflebotham Royston Shufflebotham

    Ah, I see you’ve edited the code to remove the abstract keyword, and get it to throw if an object is already present when returning. Nice one!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.