Understanding Object Pool Pattern

Object pool pattern is a creational pattern used in systems where stateless resource creation is too expensive to perform on the fly. The pattern is known to be used in database connections where we have a pool of available connections, we use one then return it back to the pool to reuse it again at a later time.

While the pattern shares similar intent with the prototype pattern in the way that it concentrates on performance (prototype pattern clones is expensive to create objects), it operates in a slightly different way. Objects are created and stored in an object pool (List or Queue) at then application start up, then consumed (reused) by one or many clients. Once a client is done using the instance, the instance state is reset and returned to the pool to wait for another client to consume it.

Implementation:

As shown in the diagram, the object pool participants are:

  • Implementation --> Represents the expensive resource to create.
  • Client --> pulls an object instance from the Pool.
  • Pool --> Wraps a limited number of available instances of the implemented type. If there is no available instance, an exception should be thrown to notify the client.
Demo Application:

Our demo application will use the object pool pattern to create overly simplified robots, use them, then return them to the pool. Robot class (this is our implementation class):

public class Robot
{
    public string Name { get; private set; }
    public string Status { get; private set; }
    public string Location { get; private set; }
    /// <summary>
    /// Initializes a new instance of the Robot class.
    /// </summary>
    public Robot(string name)
    {
        Name = name;
    }
    public void PerformAction(string action)
    {
        if (Location == null)
            throw new Exception("Location Not set, call Move with x & y coordinates");
        Status = "Performing " + action;
        ShowMessage(Status);
    }
    public void Move(int x, int y)
    {
        Location = string.Format("{0} At X {1} Y {2}", Name, x, y);
    }
    public void Reset()
    {
        ShowMessage("Resetting");
        this.Location = null;
        this.Status = null;
    }
    public void ShowMessage(string message)
    {
        Console.WriteLine("{0} {1}", Name, message);
    }
}

Robot Pool Class (this is our Object Pool class where we store the available and in-use lists of objects):

Note that the RobotPool class contains only two methods, GetRobot and Release.

class RobotPool
{
    static readonly BlockingCollection<Robot> available = new BlockingCollection<Robot>();
    static readonly BlockingCollection<Robot> inUse = new BlockingCollection<Robot>();
 
    private static int MaxPool
    {
        get
        {
            return Settings.Default.MaxPool;
        }
    }
    static RobotPool()
    {
        for (var i = 0; i < MaxPool ; i++)
        {
            available.Add(new Robot(Helpers.NumberToWords(i)));
        }
    }
 
    public static Robot GetRobot()
    {
        try
        {
            Robot robot;
            if (!available.TryTake(out robot))
            {
                throw new RobotPoolException("All Available Robots are in use");
            }
 
            inUse.Add(robot);
            return robot;
        }
        catch (RobotPoolException ex)
        {
            Console.WriteLine(ex.Message);
        }
 
        return null;
    }
    public static void Release(Robot robot)
    {
        if (robot != null)
        {
            Robot rbt = robot;
            rbt.Reset();
            available.Add(rbt);
            inUse.TryTake(out rbt);
        }
    }
}

Client to use the object Pool:

static void Main(string[] args)
{
    var pool = RobotPool.GetRobot();
    if (pool != null)
    {
        pool.Move(20, 100);
        var location = pool.Location;
        pool.PerformAction("Go to warehouse");
        pool.PerformAction("Go to Shelf 1");
        Console.WriteLine(pool.Location);
    }
    var pool2 = RobotPool.GetRobot();
    if (pool2 != null)
    {
        pool2.Move(50, 10);
        var l2 = pool2.Location;
        pool2.PerformAction("Go to Shelf 2");
        RobotPool.Release(pool2);
    }
    //  pool = RobotPool.GetRobot();
    RobotPool.Release(pool);
    Console.ReadLine();
}
Pattern's Drawbacks:

The object pool pattern suffers from two drawbacks:

  1. Releasing the instance is dependent on the client, if the client forgets to release the instance back to the pool, it will “hang” there as a wasted resource.
  2. Instances in the object pool available list often lack a time to expire. Again this is wasting expensive resources.

Both drawbacks can be easily mitigated by associating a timeout with the pooled objects.

ObjectPoolPatternDemo.zip (56.04 kb)

Comments (6) -

I am unable to download the source code, can you test that plz

cheers

Chris,
Not sure why the download link didn't work for you. I can see the file downloaded over 10 times in last few days.
Try again and let me know please.

First, Thanks for the article and demo.
Second, where do I add to the max numbers of created robots?

James,
to change the max numbers of robots in the object pool, Right click on the project, go to Settings, change the setting (MaxPool)

im not able to download..

Sandeep,

You couldn't see the download link because the format was off.
Try again please

Add comment