Wednesday, June 08, 2011

Object Pool has been redesigned.

I spent the evening learning about Generics in C#.  Using my newfound knowledge, I was able to revamp my object pool.  I knew that what I was doing initially wasn't the best approach, but it worked and it was fast.  My new version works, is just as fast and is a lot more elegant.

In the old version, I had a pool for chunks, cubes and creatures.  Each individual pool had something like this:

1:      public static Queue<chunk> chunkPool;  
2:      public static int chunkCount;  
3:      public static int numFreeChunks;  

It also had multiple methods for getting an object and putting it back.  Everytime I wanted a new pool, I had to create a new set of objects and methods.  It worked, but was ugly.  The new pool is this:

1:    public static class pool  
2:    {  
3:      public static hose<tree> treePool;  
4:      public static hose<change> changesPool;  
5:      public static hose<cube> cubePool;  
6:      public static void init()  
7:      {  
8:        treePool = new hose<tree>();  
9:        cubePool = new hose<cube>();  
10:        changesPool = new hose<change>();  
11:      }  
12:    }  

Hose<T> is a generic class that has everything embedded in it.  Creating new pools is now much cleaner and easier.

I've been testing this in the 2d version (from here on out, called 2dr) instead of the 3d (called 3dr).  Once I make sure it's cool, I'll migrate it over.

Edit:  Forgot to put this originally.  My hose class:  http://pastebin.com/mNU5qgHw


using System;
using System.Collections.Generic;

namespace R_01.classes
{
    public class hose<T>
        where T : class, new()
    {
        private Queue<T> objectPool;
        public int count;
        public int numFree;
        private bool lockObjects;

        public hose()
        {
            objectPool = new Queue<T>();
            lockObjects = false;
            numFree = 0;
            count = 0;
        }
        public T get()
        {
            while (lockObjects && !gameData.exiting) { }
            lockObjects = true;

            T obj;

            lock (objectPool)
            {
                try
                {
                    if (numFree > 0)
                    {
                        obj = objectPool.Dequeue();
                        numFree--;
                        if (obj == null)
                        {
                            obj = new T();
                            count++;
                        }
                    }
                    else
                    {
                        obj = new T();
                        count++;
                    }
                }
                catch (Exception ex)
                {
                    ex.ToString();
                    obj = new T();
                    count++;
                }
                finally
                {
                    lockObjects = false;
                }
            }

            return obj;
        }
        public void put(T obj)
        {
            while (lockObjects && !gameData.exiting) { }
            lockObjects = true;

            lock (objectPool)
            {
                try
                {
                    objectPool.Enqueue(obj);
                    numFree++;
                }
                catch (Exception ex)
                {
                    ex.ToString();
                }
                finally
                {
                    lockObjects = false;
                }
            }
        }
    }
}

3 comments:

Anonymous said...

Any particular reason you call your generic class 'hose'?

Great blog by the way. I always look forward to updates :)

Roy said...

My object pool is completely empty at first until it's filled up somehow. In order to get water (objects) into a pool, you use a hose.

I think that was my logic, haha.

Roy said...

Also, here's my hose class: http://pastebin.com/mNU5qgHw

Forgot to put it in the OP.