using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Xna.Framework;
namespace MyPoolNamespace
{
///
/// Represents a fixed-size pool of available items that can be removed
/// as needed and returned when finished.
///
public class Pool : IEnumerable where T : new()
{
///
/// Represents an entry in a Pool collection.
///
public struct Node
{
///
/// Used internally to track which entry in the Pool
/// is associated with this Node.
///
internal int NodeIndex;
///
/// Item stored in Pool.
///
public T Item;
}
///
/// Fixed Pool of item nodes.
///
private Node[] pool;
///
/// Array containing the active/available state for each item node
/// in the Pool.
///
private bool[] active;
///
/// Queue of available item node indices.
///
private Queue available;
///
/// Gets the number of available items in the Pool.
///
///
/// Retrieving this property is an O(1) operation.
///
public int AvailableCount
{
get { return available.Count; }
}
///
/// Gets the number of active items in the Pool.
///
///
/// Retrieving this property is an O(1) operation.
///
public int ActiveCount
{
get { return pool.Length - available.Count; }
}
///
/// Gets the total number of items in the Pool.
///
///
/// Retrieving this property is an O(1) operation.
///
public int Capacity
{
get { return pool.Length; }
}
///
/// Initializes a new instance of the Pool class.
///
/// Total number of items in the Pool.
///
/// Number of items is less than 1.
///
///
/// This constructor is an O(n) operation, where n is capacity.
///
public Pool(int capacity)
{
if (capacity <= 0)
{
throw new ArgumentOutOfRangeException(
"Pool must contain at least one item.");
}
pool = new Node[capacity];
active = new bool[capacity];
available = new Queue(capacity);
for (int i = 0; i < capacity; i++)
{
pool[i] = new Node();
pool[i].NodeIndex = i;
pool[i].Item = new T();
active[i] = false;
available.Enqueue(i);
}
}
///
/// Makes all items in the Pool available.
///
///
/// This method is an O(n) operation, where n is Capacity.
///
public void Clear()
{
available.Clear();
for (int i = 0; i < pool.Length; i++)
{
active[i] = false;
available.Enqueue(i);
}
}
///
/// Removes an available item from the Pool and makes it active.
///
/// The node that is removed from the available Pool.
///
/// There are no available items in the Pool.
///
///
/// This method is an O(1) operation.
///
public Node Get()
{
int nodeIndex = available.Dequeue();
active[nodeIndex] = true;
return pool[nodeIndex];
}
///
/// Returns an active item to the available Pool.
///
/// The node to return to the available Pool.
///
/// The node being returned is invalid.
///
///
/// The node being returned was not active.
/// This probably means the node was previously returned.
///
///
/// This method is an O(1) operation.
///
public void Return(Node item)
{
if ((item.NodeIndex < 0) || (item.NodeIndex > pool.Length))
{
throw new ArgumentException("Invalid item node.");
}
if (!active[item.NodeIndex])
{
throw new InvalidOperationException("Attempt to return an inactive node.");
}
active[item.NodeIndex] = false;
available.Enqueue(item.NodeIndex);
}
///
/// Sets the value of the item in the Pool associated with the
/// given node.
///
/// The node whose item value is to be set.
///
/// The node being returned is invalid.
///
///
/// This method is necessary to modify the value of a value type stored
/// in the Pool. It copies the value of the node's Item field into the
/// Pool.
/// This method is an O(1) operation.
///
public void SetItemValue(Node item)
{
if ((item.NodeIndex < 0) || (item.NodeIndex > pool.Length))
{
throw new ArgumentException("Invalid item node.");
}
pool[item.NodeIndex].Item = item.Item;
}
public bool IsActive(int index)
{
if (active[index])
return true;
else
return false;
}
///
/// Copies the active items to an existing one-dimensional Array,
/// starting at the specified array index.
///
///
/// The one-dimensional array to which active Pool items will be
/// copied.
///
///
/// The index in array at which copying begins.
///
/// The number of items copied.
///
/// This method is an O(n) operation, where n is the smaller of
/// capacity or the array length.
///
public int CopyTo(T[] array, int arrayIndex)
{
int index = arrayIndex;
foreach (Node item in pool)
{
if (active[item.NodeIndex])
{
array[index++] = item.Item;
if (index == array.Length)
{
return index - arrayIndex;
}
}
}
return index - arrayIndex;
}
///
/// Gets an enumerator that iterates through the active items
/// in the Pool.
///
/// Enumerator for the active items.
///
/// This method is an O(n) operation,
/// where n is Capacity divided by ActiveCount.
///
public IEnumerator GetEnumerator()
{
foreach (Node item in pool)
{
if (active[item.NodeIndex])
{
yield return item.Item;
}
}
}
///
/// Gets an enumerator that iterates through the active nodes
/// in the Pool.
///
///
/// This method is an O(n) operation,
/// where n is Capacity divided by ActiveCount.
///
public IEnumerable ActiveNodes
{
get
{
foreach (Node item in pool)
{
if (active[item.NodeIndex])
{
yield return item;
}
}
}
}
///
/// Gets an enumerator that iterates through all of the nodes
/// in the Pool.
///
///
/// This method is an O(1) operation.
///
public IEnumerable AllNodes
{
get
{
foreach (Node item in pool)
{
yield return item;
}
}
}
///
/// Implementation of the IEnumerable interface.
///
///
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}