This is a port of the XNA generic resource pool (http://www.xnawiki.com/index.php/Generic_Resource_Pool) in the D programming language.
module resourcepool;
import std.traits;
public final class Pool( TClass ) if( !is( TClass == struct ) && !( isIntegral!TClass || isFloatingPoint!TClass ) && !is( TClass == bool ) && !isSomeChar!TClass )
{
private alias void delegate( TClass ) Action;
private alias bool delegate( TClass ) Predicate;
private alias TClass delegate() Func;
private const int RESIZE_AMOUNT = 10;
private bool mCanResize;
private TClass[] mItems;
private Predicate mValidate;
private Func mAllocate;
private Action mInitialize;
private Action mDeinitialize;
private int mInvalidCount;
public Action Initialize() @property
{
return this.mInitialize;
}
public void Initialize( Action iAction ) @property
{
this.mInitialize = iAction;
}
public Action Deinitialize() @property
{
return this.mDeinitialize;
}
public void Deinitialize( Action iAction ) @property
{
this.mDeinitialize = iAction;
}
public int ValidCount() @property
{
return this.mItems.length - this.mInvalidCount;
}
public int InvalidCount() @property
{
return this.mInvalidCount;
}
private void InvalidCount( int count ) @property
{
this.mInvalidCount = count;
}
public TClass opIndex( int index )
{
index += this.mInvalidCount;
if( index < this.mInvalidCount || index >= this.mItems.length )
throw new Exception( "The index must be less than or equal to ValidCount." );
return this.mItems[index];
}
public this( int initialSize, bool canResize, Predicate validator, Func allocator )
in
{
assert( initialSize < 1, "initialSize must be at least 1." );
assert( validator !is null, "validator cannot be null." );
assert( allocator !is null, "allocator cannot be null." );
}
body
{
this.mCanResize = canResize;
this.mItems = new TClass[initialSize];
this.mInvalidCount = this.mItems.length;
this.mValidate = validator;
this.mAllocate = allocator;
}
public void CleanUp()
{
for( int i = this.mInvalidCount; i < this.mItems.length; ++i )
{
TClass obj = this.mItems[i];
if( this.mValidate( obj ) )
continue;
if( i != this.mInvalidCount )
{
this.mItems[i] = this.mItems[this.mInvalidCount];
this.mItems[this.mInvalidCount] = obj;
}
if( this.Deinitialize !is null )
this.Deinitialize()( obj );
++this.mInvalidCount;
}
}
public TClass New()
{
if( this.mInvalidCount == 0 )
{
if( !this.mCanResize )
return null;
this.mItems ~= new TClass[RESIZE_AMOUNT];
this.mInvalidCount += RESIZE_AMOUNT;
}
--this.mInvalidCount;
TClass obj = this.mItems[this.mInvalidCount];
if( obj is null )
{
obj = this.mAllocate();
if( obj is null )
throw new Exception( "Error allocating new resource." );
this.mItems[this.mInvalidCount] = obj;
}
if( this.Initialize !is null )
this.Initialize()( obj );
return obj;
}
}