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(); } } }