Skip to content

Instantly share code, notes, and snippets.

@SirTony
Created April 2, 2015 23:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SirTony/5730aad97f4f190f7277 to your computer and use it in GitHub Desktop.
Save SirTony/5730aad97f4f190f7277 to your computer and use it in GitHub Desktop.
A mirror of the ResourcePool<T> from xnawiki.com
/// <summary>
/// A pre-allocated pool of objects with the ability to sort
/// and maintain objects as they become invalidated.
/// </summary>
/// <typeparam name="T">The type of object the pool will hold.</typeparam>
public class ResourcePool<T> where T : class
{
#region Variables
private ValidateObject objectCheck;
private T[] objects;
private int numberOfInvalidObjects;
#endregion
#region Properties
/// <summary>
/// Gets the maximum number of objects the pool can hold.
/// </summary>
public int MaximumSize
{
get { return objects.Length; }
}
/// <summary>
/// Gets the number of invalid objects (open spaces) in the pool.
/// </summary>
public int NumberOfInvalidObjects
{
get { return numberOfInvalidObjects; }
}
/// <summary>
/// Gets the number of valid objects (filled spaces) in the pool.
/// </summary>
public int NumberOfValidObjects
{
get { return objects.Length - numberOfInvalidObjects; }
}
/// <summary>
/// Returns a valid object at the given index. Throws an exception
/// if the index points to an invalid object space.
/// </summary>
/// <param name="index">The index of the valid object to get</param>
/// <returns>A valid object found at the index</returns>
public T this[int index]
{
get
{
index += NumberOfInvalidObjects;
if (index < NumberOfInvalidObjects || index >= MaximumSize)
{
throw new IndexOutOfRangeException(
"The index must be less than or equal to NumberOfValidObjects");
}
return objects[index];
}
}
#endregion
#region Constructors
/// <summary>
/// Create a new pool with enough space for the allocated number of objects
/// </summary>
/// <param name="allocation">The number of objects to allocate space for</param>
/// <param name="objectCheck">The method used to validate objects</param>
public ResourcePool(int allocation, ValidateObject objectCheck)
: this(allocation, objectCheck, null)
{ }
/// <summary>
/// Create a new pool with enough space for the allocated number of objects
/// </summary>
/// <param name="allocation">The number of objects to allocate space for</param>
/// <param name="objectCheck">The method used to validate objects</param>
public ResourcePool(int allocation, ValidateObject objectCheck, CreateNewObject objectCreate)
{
if (objectCheck == null)
throw new Exception("ValidateObject delegate cannot be null.");
this.objectCheck = objectCheck;
numberOfInvalidObjects = allocation;
objects = new T[allocation];
for (int i = 0; i < allocation; i++)
{
if (objectCreate != null)
{
T t = objectCreate();
if (t == null)
throw new Exception("CreateNewObject delegate cannot return null.");
objects[i] = t;
}
else if (typeof(T).GetConstructor(null) != null)
objects[i] = (T)typeof(T).GetConstructor(null).Invoke(null);
else
throw new Exception(
"CreateNewObject delegate must be specified or T (" + typeof(T).ToString() + ") " +
"must implement a parameterless constructor.");
}
}
#endregion
#region Methods
/// <summary>
/// Creates a new valid object to fill the spot of an invalidated
/// object if possible. Returns null if all objects are valid.
/// </summary>
/// <returns>A reference to the next valid object, or null if all space is being used.</returns>
public T GetNewValidObject()
{
if (numberOfInvalidObjects > 0)
return objects[--numberOfInvalidObjects];
return null;
}
/// <summary>
/// Iterates through the objects checking for valid and
/// invalid objects, arranging the internal list as needed.
/// This method should be called each frame.
/// </summary>
public void ValidateObjects()
{
for (int i = numberOfInvalidObjects; i < objects.Length; i++)
{
T o = objects[i];
if (!objectCheck(o))
{
if (i != numberOfInvalidObjects)
{
objects[i] = objects[numberOfInvalidObjects];
objects[numberOfInvalidObjects] = o;
}
numberOfInvalidObjects++;
}
}
}
#endregion
#region Delegate Declarations
/// <summary>
/// Checks if an object should be flagged as
/// invalidated, allowing it's space in the pool
/// to be given to another object.
/// </summary>
/// <param name="obj">The object to check</param>
/// <returns>True if the object should be kept; false otherwise</returns>
public delegate bool ValidateObject(T obj);
/// <summary>
/// Creates a new object during initialization.
/// </summary>
/// <returns>The newly created object. Cannot return null.</returns>
public delegate T CreateNewObject();
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment