diff --git a/Nuclex.Support (Xbox 360).csproj b/Nuclex.Support (Xbox 360).csproj
index 8bf4786..0bab4fd 100644
--- a/Nuclex.Support (Xbox 360).csproj
+++ b/Nuclex.Support (Xbox 360).csproj
@@ -85,6 +85,7 @@
Deque.cs
+
ItemEventArgs.cs
@@ -109,6 +110,10 @@
ParentingCollection.cs
+
+
+ Pool.cs
+
PriorityItemPair.cs
diff --git a/Nuclex.Support.csproj b/Nuclex.Support.csproj
index 08cd1b5..06fc31a 100644
--- a/Nuclex.Support.csproj
+++ b/Nuclex.Support.csproj
@@ -71,6 +71,7 @@
Deque.cs
+
ItemEventArgs.cs
@@ -95,6 +96,10 @@
ParentingCollection.cs
+
+
+ Pool.cs
+
PriorityItemPair.cs
diff --git a/Source/Collections/IRecyclable.cs b/Source/Collections/IRecyclable.cs
new file mode 100644
index 0000000..d001e0c
--- /dev/null
+++ b/Source/Collections/IRecyclable.cs
@@ -0,0 +1,45 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
+
+namespace Nuclex.Support.Collections {
+
+ /// Allows an object to be returned to its initial state
+ ///
+ ///
+ /// This interface is typically implemented by objects which can be recycled
+ /// in order to avoid the construction overhead of a heavyweight class and to
+ /// eliminate garbage by reusing instances.
+ ///
+ ///
+ /// Recyclable objects should have a parameterless constructor and calling
+ /// their Recycle() method should bring them back into the state they were
+ /// in right after they had been constructed.
+ ///
+ ///
+ public interface IRecyclable {
+
+ /// Returns the object to its initial state
+ void Recycle();
+
+ }
+
+} // namespace Nuclex.Support.Collections
diff --git a/Source/Collections/Pool.Test.cs b/Source/Collections/Pool.Test.cs
new file mode 100644
index 0000000..029570a
--- /dev/null
+++ b/Source/Collections/Pool.Test.cs
@@ -0,0 +1,108 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+#if UNITTEST
+
+using System;
+using System.Collections.Generic;
+
+using NUnit.Framework;
+using NMock2;
+
+namespace Nuclex.Support.Collections {
+
+ /// Unit tests for the Pool class
+ [TestFixture]
+ public class PoolTest {
+
+ #region class TestClass
+
+ /// Used to test the pool
+ private class TestClass : IRecyclable {
+
+ /// Returns the object to its initial state
+ public void Recycle() {
+ this.Recycled = true;
+ }
+
+ /// Whether the instance has been recycled
+ public bool Recycled;
+
+ }
+
+ #endregion // class TestClass
+
+ ///
+ /// Verifies that the pool can return newly constructed objects
+ ///
+ [Test]
+ public void TestGet() {
+ Pool pool = new Pool();
+ Assert.IsNotNull(pool.Get());
+ }
+
+ ///
+ /// Verifies that the pool will return a recycled object if one is available
+ ///
+ [Test]
+ public void TestGetRecycled() {
+ Pool pool = new Pool();
+ pool.Redeem(new TestClass());
+
+ TestClass test = pool.Get();
+ Assert.IsTrue(test.Recycled);
+ }
+
+ ///
+ /// Tests whether the pool can redeem objects that are no longer used
+ ///
+ [Test]
+ public void TestRedeem() {
+ Pool pool = new Pool();
+ pool.Redeem(new TestClass());
+ }
+
+ ///
+ /// Tests whether the Recycle() method is called at the appropriate time
+ ///
+ [Test]
+ public void TestRecycle() {
+ Pool pool = new Pool();
+ TestClass x = new TestClass();
+
+ Assert.IsFalse(x.Recycled);
+ pool.Redeem(x);
+ Assert.IsTrue(x.Recycled);
+ }
+
+ /// Verifies that the pool's Capacity is applied correctly
+ [Test]
+ public void TestPoolSize() {
+ Pool pool = new Pool(123);
+ Assert.AreEqual(123, pool.Capacity);
+ pool.Capacity = 321;
+ Assert.AreEqual(321, pool.Capacity);
+ }
+
+ }
+
+} // namespace Nuclex.Support.Collections
+
+#endif // UNITTEST
diff --git a/Source/Collections/Pool.cs b/Source/Collections/Pool.cs
new file mode 100644
index 0000000..a0b4a8a
--- /dev/null
+++ b/Source/Collections/Pool.cs
@@ -0,0 +1,131 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Nuclex.Support.Collections {
+
+ /// Pool that recycles objects in order to avoid garbage build-up
+ /// Type of objects being pooled
+ ///
+ ///
+ /// Use this class to recycle objects instead of letting them become garbage,
+ /// creating new instances each time. The Pool class is designed to either be
+ /// used on its own or as a building block for a static class that wraps it.
+ ///
+ ///
+ /// Special care has to be taken to revert the entire state of a recycled
+ /// object when it is returned to the pool. For example, events will need to
+ /// have their subscriber lists emptied to avoid sending out events to the
+ /// wrong subscribers and accumulating more and more subscribers each time
+ /// they are reused.
+ ///
+ ///
+ /// To simplify such cleanup, pooled objects can implement the IRecyclable
+ /// interface. When an object is returned to the pool, the pool will
+ /// automatically call its IRecyclable.Recycle() method.
+ ///
+ ///
+ public class Pool where ItemType : class, new() {
+
+ /// Default number of recyclable objects the pool will store
+ public const int DefaultPoolSize = 64;
+
+ /// Initializes a new pool using the default capacity
+ public Pool() : this(DefaultPoolSize) { }
+
+ /// Initializes a new pool using a user-specified capacity
+ /// Capacity of the pool
+ public Pool(int capacity) {
+ Capacity = capacity;
+ }
+
+ ///
+ /// Returns a new or recycled instance of the types managed by the pool
+ ///
+ /// A new or recycled instance
+ public ItemType Get() {
+ lock(this) {
+ if(this.items.Count > 0) {
+ return this.items.Dequeue();
+ } else {
+ return new ItemType();
+ }
+ }
+ }
+
+ ///
+ /// Redeems an instance that is no longer used to be recycled by the pool
+ ///
+ /// The instance that will be redeemed
+ public void Redeem(ItemType item) {
+
+ // Call Recycle() when the object is redeemed (instead of when it leaves
+ // the pool again) in order to eliminate any references the object may hold
+ // to other objects.
+ callRecycleIfSupported(item);
+
+ lock(this) {
+ if(this.items.Count < this.capacity) {
+ this.items.Enqueue(item);
+ }
+ }
+ }
+
+ /// Number of objects the pool can retain
+ ///
+ /// Changing this value causes the pool to be emtpied. It is recommended that
+ /// you only read the pool's capacity, never change it.
+ ///
+ public int Capacity {
+ get { return this.capacity; }
+ set {
+ this.capacity = value;
+ this.items = new Queue(value);
+ }
+ }
+
+ ///
+ /// Calls the Recycle() method on an objects if it implements
+ /// the IRecyclable interface
+ ///
+ ///
+ /// Object whose Recycle() method will be called if supported by the object
+ ///
+ private static void callRecycleIfSupported(ItemType item) {
+ IRecyclable recycleable = item as IRecyclable;
+ if(recycleable != null) {
+ recycleable.Recycle();
+ }
+ }
+
+ /// Objects being retained for recycling
+ private Queue items;
+ /// Capacity of the pool
+ ///
+ /// Required because the Queue class doesn't allow this value to be retrieved
+ ///
+ private int capacity;
+
+ }
+
+} // namespace Nuclex.Support.Collections
diff --git a/Source/Collections/PriorityItemPair.Test.cs b/Source/Collections/PriorityItemPair.Test.cs
index 918f913..4df1e0f 100644
--- a/Source/Collections/PriorityItemPair.Test.cs
+++ b/Source/Collections/PriorityItemPair.Test.cs
@@ -18,11 +18,11 @@ License along with this library
*/
#endregion
+#if UNITTEST
+
using System;
using System.Collections.Generic;
-#if UNITTEST
-
using NUnit.Framework;
using NMock2;