Game Development Community

Object Pooling / Recycling

by Jeremy Easoz · in Torque Game Builder · 09/25/2008 (9:41 am) · 3 replies

Currently I have a bare bones ObjectPooling and Recycling ScriptGroup.
I'm having two problems with it currently.

1. Recycling Objects
I'm not really sure how to go about doing it.
function TObjectPool::pool_object(%this, %objPoolSize)
{
for(%i = 0; %i < %objPoolSize; %i++)
{
%pooledObj = new t2dAnimatedSprite();
%this.add(%pooledObj);
}
}
After I use an object I just remove it from the pool and eventually the pool will run out.

2. Pooling
function TObjectPool::pool_object(%this, %objPoolSize)
{
for(%i = 0; %i < %objPoolSize; %i++)
{
%pooledObj = new t2dAnimatedSprite();
%this.add(%pooledObj);
}
}

As you can see the above function will only pool a t2dAnimatedSprite().
Is there a way I can pass in an object type. Something like below (doesnt work)
function TObjectPool::pool_object(%this, %objType, %objPoolSize)
{
for(%i = 0; %i < %objPoolSize; %i++)
{
%pooledObj = new %objType @ "();";
%this.add(%pooledObj);
}
}

#1
09/25/2008 (11:37 am)
This is completely off the top of my head and untested but I guess I would propably do something like this:

// Define a factory function for every object type
function Create_t2dSceneObject()
{
    return new t2dSceneObject();
}

function Create_t2dStaticSprite()
{
    return new t2dStaticSprite();
}

function Create_t2dAnimatedSprite()
{
    return new t2dAnimatedSprite();
}

...

function Create_t2dTrigger()
{
    return new t2dTrigger();
}


// Define the pool class
function ObjectPoolClass::PullObjectOut( %this )
{
    %freeList = %this.FreeList;
    %objectCount = %freeList.getCount();

    if ( %objectCount != 0 )
    {
         %object = %freeList.getObject( %objectCount - 1 );
         %freeList.remove( %object );
         return %object;
    }
    else
    {
         return call( %this.FactoryMethod );
    }
}

function ObjectPoolClass::ThrowObjectBackIn( %this, %object )
{
    %this.FreeList.Add( %object );

    // Comment this out in non-debug builds
    if ( %object.class !$= %this.ObjectClassName )
    {
         error( "ObjectPoolClass::ThrowObjectBackIn() - Wrong Pool!" );
         error( "Cannot throw" SPC %object.class SPC "in" SPC %this.ObjectClassName SPC "pool." );
    }
}

function Create_ObjectPool( %objectClassName, %initialSize )
{
     %pool = new t2dSceneObject( %objectClassName @ "_ObjectPool" )
     {
          class = "ObjectPoolClass";
     };

     %pool.FreeList = new SimSet();
     %pool.ObjectClassName = %objectClassName; 
     %pool.FactoryMethod = "Create_" @ %objectClassName;

     for ( %i = 0; %i < %initialSize; %i++  )
     {
           %pool.FreeList.Add( call( %pool.FactoryMethod ) );
     }

     return %pool;
}

function ObjectPoolClass::destroy( %this )
{
     while ( %this.FreeList.GetCount() > 0 )
     {
           %object = %this.FreeList.GetObject( 0 );
           %this.FreeList.Remove( %object );
           %object.SafeDelete();
     }

     %this.SafeDelete();
}


// Then create the various pools ...

$SceneObjectPool = Create_ObjectPool( "t2dSceneObject", 50 );
$StaticSpritePool = Create_ObjectPool( "t2dStaticSprite", 50 );
$AnimatedSpritePool = Create_ObjectPool( "t2dAnimatedSprite", 50 );
// ... and all other classes you need


// ... and use them like this
%someObject  = $AnimatedSpritePool.PullObjectOut();
%someObject.blubb();
$AnimatedSpritePool.ThrowObjectBackIn( %someObject );

Edit:
But as all of this runs in script, chances are not bad that it is actually slower than just using new and delete. I don't know. Heap fragmentation could still be an argument for using object pooling.

-Michael
#2
09/25/2008 (11:57 am)
You can add object's of different types into a SimSet, but if you intermix them it will make getting one of the proper type out of the pool perform a lot worse since you need to loop through until you hit one of the type you want.

Something like what Michael posted would allow you reuse some of the pooler-object code to easily create pools of different types though.

Interestingly enough, you might not actually need a factory method that gets call(ed). Something like this actually works.

%obj = new ("classType")();
#3
09/25/2008 (1:42 pm)
It really does. I didn't know that. Thanks James.